📄 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()
//-----------------------------------------------------------------------------
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -