www.pudn.com > zmodemclass.zip > ZModemComm.cpp


//----------------------------------------------------------------------------- 
// project:		ZModem 
// author:		Frank Weiler, Genshagen, Germany 
// version:		0.91 
// date:		October 10, 2000 
// email:		frank@weilersplace.de 
// copyright:	This Software is OpenSource. 
// file:		ZModemComm.cpp 
// description:	a class to handle all the communication stuff for ZModem 
//----------------------------------------------------------------------------- 
 
#include "stdafx.h" 
#include "ZModemComm.h" 
#include "ZModemCore.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
//----------------------------------------------------------------------------- 
CZModemComm::CZModemComm(HANDLE hcomm,HANDLE hCancelEvent) 
//----------------------------------------------------------------------------- 
{ 
	m_hcomm = hcomm; 
	m_hCancelEvent = hCancelEvent; 
} 
 
//----------------------------------------------------------------------------- 
CZModemComm::~CZModemComm() 
//----------------------------------------------------------------------------- 
{ 
 
} 
 
//----------------------------------------------------------------------------- 
DWORD CZModemComm::ReadBuffer(void *buffer, DWORD num) 
//----------------------------------------------------------------------------- 
{	//Variablen 
	DWORD dwRead,numWaiting; 
	COMSTAT cst; 
	DWORD err; 
	//Routine 
	if(!ClearCommError(m_hcomm,&err,&cst)) 
	{ 
		TRACE("error ClearCommError() %lu\n",GetLastError()); 
		return(0); 
	} 
	numWaiting=cst.cbInQue; 
	if(numWaiting==0) 
		return(0); 
	if(num > numWaiting) 
		num = numWaiting; 
	//start overlapped io 
	OVERLAPPED ov={0,0,0,0,NULL}; 
	ov.hEvent=CreateEvent(NULL,true,true,NULL); 
	HANDLE waitfor[2]; 
	waitfor[0]=m_hCancelEvent; 
	waitfor[1]=ov.hEvent; 
	DWORD dwHandleSignaled; 
	if(!SetupReadEvent(&ov,buffer,num,&dwRead)) 
	{ 
		while(true) 
		{ 
			dwHandleSignaled=WaitForMultipleObjects(2,waitfor,false,10000); 
			// Which event occured? 
			switch(dwHandleSignaled) 
			{ 
				case WAIT_OBJECT_0:    //cancelled 
				{   // Time to exit. 
   					SetLastError(ZMODEM_ABORTFROMOUTSIDE); 
      				goto EndZModem; 
				} 
   				case WAIT_OBJECT_0 + 1: // ReadEvent signaled. 
      			{ 
         			if(HandleReadEvent(&ov,buffer,num,&dwRead)) 
						goto EndZModem; 
					break; 
				} 
	   			default: 
            		goto EndZModem; 
			}  
		} 
	} 
EndZModem: 
	CloseHandle(ov.hEvent); 
	//all data received 
	return(dwRead); 
} 
 
//----------------------------------------------------------------------------- 
DWORD CZModemComm::WriteBuffer(void *buffer, DWORD num) 
//----------------------------------------------------------------------------- 
{ 
 
	HANDLE HandlesToWaitFor[2]; 
	DWORD start=0; 
	DWORD dwLastError; 
	OVERLAPPED ow={0,0,0,0,NULL}; 
	ow.hEvent=CreateEvent(NULL,true,true,NULL); 
	DWORD dwNumberOfBytesWritten; 
	DWORD dwHandleSignaled; 
 
	HandlesToWaitFor[0]=m_hCancelEvent; 
	HandlesToWaitFor[1]=ow.hEvent; 
	// Keep looping until all characters have been written. 
	do 
	{	// Start the overlapped I/O. 
		if(!WriteFile(m_hcomm,(char*)(buffer)+start,num,&dwNumberOfBytesWritten,&ow)) 
		{  // WriteFile failed.  Expected; lets handle it. 
			dwLastError=GetLastError(); 
			if(dwLastError==ERROR_INVALID_HANDLE) 
				return(0); 
			if(dwLastError!=ERROR_IO_PENDING) 
				return(0); 
			dwHandleSignaled=WaitForMultipleObjects(2,HandlesToWaitFor,false,INFINITE); 
			switch(dwHandleSignaled) 
			{ 
				case WAIT_OBJECT_0:// CloseEvent signaled! 
					return(0); 
           	case WAIT_OBJECT_0 + 1: // Wait finished. 
					break; 
				default: // This case should never occur. 
					return(0); 
			} 
			if(!GetOverlappedResult(m_hcomm,&ow,&dwNumberOfBytesWritten,true)) 
			{ 
				dwLastError=GetLastError(); 
				// Its possible for this error to occur if the 
				// service provider has closed the port. 
				if(dwLastError==ERROR_INVALID_HANDLE) 
					return(0); 
				return(0); 
			} 
         else 
          	SetLastError(0); 
		} 
		num -= dwNumberOfBytesWritten; 
		start += dwNumberOfBytesWritten; 
	} 
	while(num > 0);  // Write the whole thing! 
	CloseHandle(ow.hEvent); 
	return(start); 
} 
 
//----------------------------------------------------------------------------- 
bool CZModemComm::SetupReadEvent(LPOVERLAPPED lpOverlappedRead,void* lpszInputBuffer, 
					           DWORD dwSizeofBuffer,LPDWORD lpnNumberOfBytesRead) 
//----------------------------------------------------------------------------- 
{	 
	DWORD dwLastError; 
    
	if(ReadFile(m_hcomm,lpszInputBuffer,dwSizeofBuffer,lpnNumberOfBytesRead, 
   				lpOverlappedRead)) 
	{ 
		TRACE("ReadFile successful in SetupReadEvent"); 
		return(true); 
	} 
	// ReadFile failed.  Expected because of overlapped I/O. 
	dwLastError=GetLastError(); 
	// LastError was ERROR_IO_PENDING, as expected. 
	if(dwLastError==ERROR_IO_PENDING) 
		return(false); 
	SetLastError(ZMODEM_TIMEOUT); 
	return(true);//ok 
} 
 
//----------------------------------------------------------------------------- 
bool CZModemComm::HandleReadEvent(LPOVERLAPPED lpOverlappedRead,void* lpszInputBuffer, 
						         DWORD dwSizeofBuffer,LPDWORD lpnNumberOfBytesRead) 
//----------------------------------------------------------------------------- 
{ 
	if(GetOverlappedResult(m_hcomm,lpOverlappedRead,lpnNumberOfBytesRead,true)) 
	{ 
		TRACE("GetOverlapped succesfull in HandleReadEvent"); 
  		SetLastError(0); 
	  	return(true); 
	} 
	return(false); 
} 
 
//----------------------------------------------------------------------------- 
void CZModemComm::GetBlock(void *buffer,DWORD max,LPDWORD actual) 
//----------------------------------------------------------------------------- 
{	//Variablen 
	int x; 
	//Routine 
	x= ReadBuffer(buffer,max); 
	if(x==0) 
	{ 
		for (int cnt=0;cnt<400;cnt++) 
		{ 
			Sleep(10); 
			x= ReadBuffer(buffer,max); 
			if(x!=0) 
				break; 
		} 
	} 
	if(x==0) 
	{ 
		TRACE("Setze Fehler %s\n","ZMODEM_TIMEOUT"); 
		SetLastError(ZMODEM_TIMEOUT); 
	} 
	*actual = x; 
} 
 
//----------------------------------------------------------------------------- 
void CZModemComm::GetBlockImm(void *buffer,DWORD max,LPDWORD actual) 
//----------------------------------------------------------------------------- 
{	 
	int x; 
	 
	x= ReadBuffer(buffer,max); 
	if(x==0) 
	{ 
		TRACE("set error %s\n","ZMODEM_TIMEOUT"); 
		SetLastError(ZMODEM_TIMEOUT); 
	} 
	*actual=x; 
} 
 
//----------------------------------------------------------------------------- 
DWORD CZModemComm::WriteBlock(void* buf,DWORD max) 
//----------------------------------------------------------------------------- 
{ 
	return WriteBuffer(buf,max); 
} 
 
//----------------------------------------------------------------------------- 
void CZModemComm::ClearInbound() 
//----------------------------------------------------------------------------- 
{ 
	if(!PurgeComm(m_hcomm,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR)) 
	{ 
		TRACE("error PurgeComm %lu\n",GetLastError()); 
	} 
} 
 
//----------------------------------------------------------------------------- 
void CZModemComm::ResetAll() 
//----------------------------------------------------------------------------- 
{ 
		 
}