Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

836 lines
23 KiB

/* File: C:\WACKER\xfer\hpr_rcv1.c (Created: 24-Jan-1994)
* created from HAWIN source file
* hpr_rcv1.c -- Routines to implement HyperProtocol receiver.
*
* Copyright 1989,1993,1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 1 $
* $Date: 10/05/98 1:16p $
*/
// #define DEBUGSTR
#include <windows.h>
#include <setjmp.h>
#include <stdlib.h>
#include <time.h>
#include <term\res.h>
#include <sys\types.h>
#include <sys\utime.h>
#include <tdll\stdtyp.h>
#include <tdll\mc.h>
#include <tdll\com.h>
#include <tdll\assert.h>
#include <tdll\session.h>
#include <tdll\load_res.h>
#include <tdll\xfer_msc.h>
#include <tdll\globals.h>
#include <tdll\file_io.h>
#if !defined(BYTE)
#define BYTE unsigned char
#endif
#include "cmprs.h"
#include "itime.h"
#include "xfr_dsp.h"
#include "xfr_todo.h"
#include "xfr_srvc.h"
#include "xfer.h"
#include "xfer.hh"
#include "xfer_tsc.h"
#include "hpr.h"
#include "hpr.hh"
#include "hpr_sd.hh"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_decode_msg
*
* DESCRIPTION:
* Called when a complete message has been received to decode the fields
* of the message. Messages are composed of printable characters in one
* or more fields separated by semicolons. Each field within a message
* is considered to be independent of any others but fields are guaranteed
* to be examined left to right with a message. Fields containing badly
* formatted information generate an error but fields containing unrecognized
* data are ignored.
* Note also that certain message fields may prevent subsequent fields from
* being decoded. For instance, if a partial data block 'P' field indicates
* that the previous data block was no good, a restart will be requested
* immediately and any undecoded fields will be ignored.
*
* ARGUMENTS:
* mdata -- A pointer to the printable string that contains the message
* fields.
*
* RETURNS:
* A status code which can be one of:
* H_OK if all fields were decoded without incident
* H_BADMSGFMT if a field is of a recognized type but contains badly
* formatted data.
* H_NORESYNCH if a restart was needed as the result of a field but
* could not be completed.
* H_FILEERR if a file error occurred while processing a field
* H_COMPLETE if the end of transfer field was encountered.
*/
int hr_decode_msg(struct s_hc *hc, BYTE *mdata)
{
HCOM hCom;
BYTE *field;
BYTE mstr[20];
int result = H_OK, retval, HRE_code;
int i;
BYTE typecode;
struct st_rcv_open stRcv;
hCom = sessQueryComHdl(hc->hSession);
// field = _fstrtok(mdata, FstrScolon());
field = strtok(mdata, ";");
while (field != NULL)
{
switch(typecode = *field++)
{
case 'N' : /* number of files to expect */
if (!hc->rc.files_expected)
{
hc->rc.files_expected = (int)atol(field);
if (hc->rc.files_expected > 1 && hc->rc.single_file &&
!hr_cancel(hc, HRE_TOO_MANY))
return(H_BADMSGFMT); /* this may need a new status */
hrdsp_filecnt(hc, hc->rc.files_expected);
}
break;
case 'S' : /* size in bytes of all files */
if (hc->rc.bytes_expected == -1L)
{
if ((hc->rc.bytes_expected = atol(field)) <= 0)
hc->rc.bytes_expected = -1L;
else
hrdsp_totalsize(hc, hc->rc.bytes_expected);
}
break;
case 'A' : /* abort current file */
hrdsp_event(hc, HRE_RMTABORT);
if (hc->fhdl)
hr_closefile(hc, HRE_RMTABORT);
break;
case 'P' : /* check partial block */
if ((int)atol(field) != (hc->blocksize - hc->datacnt)
|| (field = strchr(field, ',')) == NULL
|| (unsigned)atol(field + 1)
!= (hc->usecrc ? hc->h_crc : hc->h_checksum))
if (!hr_restart(hc, HRE_DATAERR))
return(H_NORESYNCH);
hc->rc.checkpoint = hc->h_filebytes;
hc->datacnt = hc->blocksize;
hc->h_checksum = hc->h_crc = 0;
break;
case 'F' : /* new file */
if (hc->current_filen && hc->fhdl && !hr_closefile(hc, HRE_NONE))
return(H_FILEERR);
/* set up for new file */
hc->h_filebytes = hc->rc.checkpoint = 0L;
hc->rc.filesize = -1L;
hc->rc.ul_lstw = 0; /* don't know date/time */
if ((int)atol(field) != ++hc->current_filen ||
(field = strchr(field, ',')) == NULL)
return(H_BADMSGFMT);
strcpy(hc->rc.rmtfname, ++field);
hc->rc.filesize = -1L;
/* set up argument structure and let transfer open the file
*/
stRcv.pszSuggestedName = hc->rc.rmtfname;
stRcv.pszActualName = hc->rc.ourfname;
/* TODO: figure out how this time stuff works */
stRcv.lFileTime = hc->rc.ul_cmp;
// stRcv.pfnVscanOutput = hr_virus_detect;
// stRcv.pfnVscanOutput = (VOID (FAR *)(VOID FAR *, USHORT))hc->rc.pfVirusCheck;
// stRcv.ssmchVscanHdl = hc->rc.ssmchVscan;
if ((retval = xfer_open_rcv_file(hc->hSession, &stRcv, 0L)) != 0)
{
switch (retval)
{
case -6:
HRE_code = HRE_USER_REFUSED;
break;
case -5:
HRE_code = HRE_DISK_ERR;
break;
case -4:
HRE_code = HRE_NO_FILETIME;
break;
case -3:
HRE_code = HRE_CANT_OPEN;
break;
case -2:
HRE_code = HRE_OLDER_FILE;
break;
case -1:
default:
HRE_code = HRE_CANT_OPEN;
break;
}
if (!hr_cancel(hc, HRE_code))
return(H_FILEERR);
}
hc->fhdl = stRcv.bfHdl;
hc->rc.basesize = stRcv.lInitialSize;
// hc->rc.ssmchVscan = stRcv.ssmchVscanHdl;
// xferMsgVirusScan(hSession, (hc->rc.ssmchVscan == (SSHDLMCH)0) ? 0:1);
// hc->rc.virus_detected = FALSE;
hrdsp_compress(hc, FALSE);
hrdsp_newfile(hc, hc->current_filen, hc->rc.rmtfname, hc->rc.ourfname);
hc->datacnt = hc->blocksize;
hc->h_checksum = hc->h_crc = 0;
/* If there is no valid compare time, then the /N option is not
* being used or there is no existing file and we can set up to
* store received data. If there is a compare time, keep tossing
* characters until we've verified that the incoming file is
* newer than what we have.
*/
if (hc->rc.ul_cmp == (unsigned long)(-1))
hc->rc.hr_ptr_putc = hr_toss;
//else if (hc->rc.ssmchVscan == (SSHDLMCH)0)/* is virscan active? */
// hc->rc.hr_ptr_putc = hr_putc;
// else
//hc->rc.hr_ptr_putc = hr_putc_vir;
else
hc->rc.hr_ptr_putc = hr_putc;
break;
case 'V' : /* Version identifier from sender */
i = (int)atol(field);
if ((field = strchr(field, ',')) == NULL)
return(H_BADMSGFMT);
/* if version restrictions were found, stop the transfer */
if (hpr_id_check(hc, i, ++field))
break;
/* else fall through */
case 'X' :
if (hc->rc.cancel_reason == HRE_NONE)
hc->rc.cancel_reason = HRE_RMTABORT;
hrdsp_event(hc, hc->rc.cancel_reason);
/* fall through */
case 'E' : /* end of transfer */
omsg_new(hc, 'c');
// StrFmt(mstr, "E%d", hc->current_filen + 1);
wsprintf(mstr, "E%d", hc->current_filen + 1);
omsg_add(hc, mstr);
// RemoteClear(); /* get rid of any prod messages */
ComRcvBufrClear(hCom);
/* Sending the next message as a burst causes the excess characters
* to be sent to the remote system after the transfer has ended,
* perhaps causing them to dither on the display. It is tempting
* to send a single message rather that a burst, but the receiver
* is going to assume the transfer is done and exit after sending
* this message so there is no chance for an error recovery if
* the message is hit.
*/
omsg_send(hc, BURSTSIZE, FALSE, TRUE);
hc->xfertime = interval(hc->xfertimer);
hrdsp_status(hc, typecode == 'E' ? HRS_COMPLETE : HRS_CANCELLED);
if (hc->current_filen > 0 && hc->fhdl)
{
if (typecode == 'E')
{
if (!hr_closefile(hc, HRE_NONE))
return(H_FILEERR);
}
else
hr_closefile(hc, hc->rc.cancel_reason);
}
return(H_COMPLETE);
case 'C' :
if (strlen(field) == 0 &&
!decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE))
{
result = H_FILEERR;
}
else
{
hrdsp_compress(hc, TRUE);
hc->rc.using_compression = TRUE;
hrdsp_status(hc, HRS_REC);
}
break;
case 's' :
if ((hc->rc.filesize = atol(field)) > 0)
hrdsp_filesize(hc, hc->rc.filesize);
break;
case 't' : /* file time/date */
{
unsigned long ulTime;
struct tm stT;
memset(&stT, 0, sizeof(struct tm));
stT.tm_year = atoi(field); /* ?? adjust */
if ((field = strchr(field, ',')) != NULL)
stT.tm_mon = atoi(++field);
if (field != NULL && (field = strchr(field, ',')) != NULL)
stT.tm_mday = atoi(++field);
if (field != NULL && (field = strchr(field, ',')) != NULL)
stT.tm_hour = atoi(++field);
if (field != NULL && (field = strchr(field, ',')) != NULL)
stT.tm_min = atoi(++field);
if (field != NULL && (field = strchr(field, ',')) != NULL)
stT.tm_sec = atoi(++field);
ulTime = mktime(&stT);
if ((long)ulTime == (-1))
ulTime = 0;
else
ulTime -= itimeGetBasetime();
hc->rc.ul_lstw = ulTime;
/*
* if hc->rc.ul_cmp contains a valid date/time, it means that
* the /N options was used and the file being received already
* exists. Compare the two times and reject any file that is
* not newer than what we already have.
*/
if (hc->rc.ul_cmp != 0)
{
if (hc->rc.ul_cmp >= hc->rc.ul_lstw)
{
/* reject incoming file */
hr_reject_file(hc, HRE_OLDER_FILE);
hc->rc.ul_cmp = (unsigned long)(-1);
}
else
{
/* everything is OK */
// if (hc->rc.ssmchVscan == (SSHDLMCH)0)
hc->rc.hr_ptr_putc = hr_putc; /* no virus checking */
// else
// hc->rc.hr_ptr_putc = hr_putc_vir; /* use vir check */
hc->rc.ul_cmp = 0;
}
}
}
break;
case 'B' :
hc->blocksize = (int)atol(field);
break;
case 'D' :
hc->deadmantime = atol(field) * 10;
break;
case 'I' :
hr_still_alive(hc, TRUE, FALSE);
break;
case 'T' :
if ((i = (int)atol(field)) == 1)
hc->usecrc = FALSE;
else if (i == 2)
hc->usecrc = TRUE;
else
result = H_BADMSGFMT;
break;
default:
/* ignore, might be option supported in later version */
break;
}
// field = _fstrtok(NULL, FstrScolon());
field = strtok(NULL, ";");
}
return(result);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_reject_file
*
* DESCRIPTION:
* Called when we are trying to reject a file that we are receiving.
*
* ARGUEMENTS:
* reason -- why we are rejecting the file
*
* RETURNS:
* Always TRUE
*/
int hr_reject_file(struct s_hc *hc, int reason)
{
BYTE mstr[20];
/* reject incoming file */
omsg_new(hc, 'c');
wsprintf(mstr, "A%d", hc->current_filen);
omsg_add(hc, mstr);
omsg_send(hc, BURSTSIZE, FALSE, TRUE);
hrdsp_event(hc, reason);
hr_closefile(hc, reason);
return TRUE;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_closefile
*
* DESCRIPTION:
* Called when the receiver is through saving to a particular file prior
* to switching to another file or finishing the transfer.
*
* ARGUMENTS:
* reason -- an event code indicating why this file is being closed
*
* RETURNS:
* TRUE if file is closed without problem.
* FALSE if an error occurred while closing.
*/
int hr_closefile(struct s_hc *hc, int reason)
{
int retcode;
hrdsp_progress(hc, FILE_DONE);
hc->total_thru += hc->h_filebytes;
hc->total_dsp += ((hc->rc.filesize == -1) ? hc->h_filebytes : hc->rc.filesize);
if (hc->fhdl != NULL)
{
// retcode = transfer_close_rcv_file(hc->fhdl, hr_result_codes[reason],
retcode = xfer_close_rcv_file(hc->hSession,
hc->fhdl,
hr_result_codes[reason],
hc->rc.rmtfname,
hc->rc.ourfname,
xfer_save_partial(hc->hSession),
hc->h_filebytes + hc->rc.basesize,
hc->h_useattr ? hc->rc.ul_lstw : 0L);
}
hc->fhdl = NULL;
hc->h_filebytes = 0;
hc->rc.using_compression = FALSE;
hc->rc.hr_ptr_putc = hr_toss;
return retcode;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_cancel
*
* DESCRIPTION:
* This routine is called when a problem or interruption during receiving
* forces a cancellation of the transfer. This routine attempts to inform
* the sender of the cancellation so that a graceful shutdown can be
* accomplished.
* It is up to the sender to actually shut down the transfer. We just send
* an interruption message to the sender asking him to do so.
*
* ARGUMENTS:
* reason -- A code providing the reason we must cancel. The reason codes
* are the same as the receiver event codes defined in the header
* file as HRE_*****
*
* RETURNS:
* TRUE if the sender responded to our request within a reasonable time.
* FALSE if the sender did not respond.
*
*/
int hr_cancel(struct s_hc *hc, int reason)
{
HCOM hCom;
BYTE str[40];
hCom = sessQueryComHdl(hc->hSession);
if (hc->rc.cancel_reason == HRE_NONE)
hc->rc.cancel_reason = reason;
if (reason == HRE_LOST_CARR)
return FALSE;
omsg_new(hc, 'c');
// StrFmt(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
wsprintf(str, "X;R%d,%lu", hc->current_filen, hc->rc.checkpoint);
DbgOutStr("%s\r\n", (LPSTR)str, 0,0,0,0);
omsg_add(hc, str);
hc->rc.hr_ptr_putc = hr_toss;
// RemoteClear();
ComRcvBufrClear(hCom);
hc->h_filebytes = hc->rc.checkpoint;
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
return(hr_resynch(hc, reason));
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_restart
*
* DESCRIPTION:
* This routine is called when an error in the received data forces us
* to restart the transfer at the last known good location. This routine
* formats the interruption request message to the sender, sends the first
* message, then passes control to hr_resynch to figure out when and if
* the sender responds.
*
* ARGUMENTS:
* reason -- A code indicating the reason for the restart. The codes used
* are the receiver event codes itemized in the header file as
* HRE_*****
*
* RETURNS:
* TRUE if sender responds to the restart request.
* FALSE if the sender does not respond within a reasonable time.
*/
int hr_restart(struct s_hc *hc, int reason)
{
HCOM hCom;
BYTE str[15];
hCom = sessQueryComHdl(hc->hSession);
omsg_new(hc, 'c');
// StrFmt(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
wsprintf(str, "R%d,%lu", hc->current_filen, hc->rc.checkpoint);
omsg_add(hc, str);
// RemoteClear();
ComRcvBufrClear(hCom);
/* Don't start accepting characters if file is being rejected due to
* /N option and there is a file open to receive them.
*/
if ((hc->rc.ul_cmp == (unsigned long)(-1)) && (hc->fhdl != NULL))
// hc->rc.hr_ptr_putc = (hc->rc.ssmchVscan == (SSHDLMCH)0) ? hr_putc : hr_putc_vir;
hc->rc.hr_ptr_putc = hr_putc;
else
hc->rc.hr_ptr_putc = hr_toss;
if (hc->rc.using_compression)
decompress_start(&hc->rc.hr_ptr_putc, hc, FALSE);
hc->h_filebytes = hc->rc.checkpoint;
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
if (hc->fhdl)
{
fio_seek(hc->fhdl,
(long)hc->rc.checkpoint + hc->rc.basesize,
FIO_SEEK_SET);
}
return(hr_resynch(hc, reason));
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_resynch
*
* DESCRIPTION:
* Attempts to resynchronize the receiver with the data stream coming
* from the sender. This routine is called when the receiver starts or
* after any interruption where the receiver asked the sender to restart
* its sending from a new location. The calling routine will have already
* sent the first copy of the restart message to the sender. This routine
* will monitor all messages arriving from the sender, looking for a
* restart message that matches the last request sent out. This routine
* will resend the restart request message at intervals to account for
* possible data loss or error in either the receiver message or the
* response from the sender.
*
* ARGUMENTS:
* hSession -- The session handle
* reason -- A reason code describing why the resynch must be performed.
* This will be HRE_NONE only in the case of initial startup.
*
* RETURNS:
* TRUE if resynch was successful.
* FALSE if resynch failed
*/
int hr_resynch(struct s_hc *hc, int reason)
{
HCOM hCom;
int fStarted = FALSE;
int tries = 0;
int try_limit = 0;
int request_again = FALSE; /* first request already made */
int result, i, j;
int iret;
// long l;
long timer, time_limit;
TCHAR rcode;
int mtype;
BYTE *msgdata;
BYTE *field;
int ok;
struct
{
int msgn;
long time;
} request_tbl[MAX_START_TRIES];
/* this variable is not accessed if NOTIMEOUTS is on */
long tmptime; /*lint -esym(550,tmptime)*/
hCom = sessQueryComHdl(hc->hSession);
// reason will be HRE_NONE only if this is the initial resynch call
// so we will set fStarted appropriately and use it to control behavior
// later on
if (reason == HRE_NONE)
{
fStarted = FALSE;
try_limit = MAX_START_TRIES;
}
else
{
fStarted = TRUE;
try_limit = MAXRETRIES;
hrdsp_event(hc, reason);
hrdsp_status(hc, HRS_REQRESYNCH);
++hc->total_tries;
hrdsp_errorcnt(hc, hc->total_tries);
}
// time_limit = RESYNCH_TIME; // MOBIDEM
j = hc->h_resynctime;
j *= 10;
if (j == 0)
j = RESYNCH_TIME;
time_limit = j;
request_tbl[0].msgn = omsg_number(hc);
timer = request_tbl[0].time = startinterval();
DbgOutStr("Initial:%d, %ld, %ld\r\n",
request_tbl[0].msgn, timer, time_limit, 0, 0);
for ( ; ; )
{
if (request_again)
{
if (++tries >= try_limit)
{
hrdsp_status(hc, HRS_CANCELLED);
if (hc->rc.cancel_reason == HRE_NONE)
hc->rc.cancel_reason = HRE_RETRYERR;
return(FALSE);
}
if (fStarted)
omsg_send(hc, BURSTSIZE, FALSE, FALSE);
else
omsg_send(hc, 1, FALSE, TRUE);
// Record this attempt in the table so we can match up responses
request_tbl[tries].msgn = omsg_number(hc);
timer = request_tbl[tries].time = startinterval();
++hc->total_tries;
hrdsp_errorcnt(hc, hc->total_tries);
request_again = FALSE;
DbgOutStr("Restart:%d, %0ld, %0ld\r\n",
request_tbl[tries].msgn, timer, time_limit, 0, 0);
}
iret = xfer_user_interrupt(hc->hSession);
if (iret == XFER_ABORT)
{
if (!fStarted || hc->ucancel)
return(FALSE);
else
{
return(hr_cancel(hc, HRE_USRCANCEL));
}
}
else if (iret == XFER_SKIP)
{
hr_reject_file(hc, HRE_USER_SKIP);
}
if (xfer_carrier_lost(hc->hSession))
return hr_cancel(hc, HRE_LOST_CARR);
#if !defined(NOTIMEOUTS)
if ((tmptime = interval(timer)) > time_limit)
{
request_again = TRUE;
if (fStarted)
// time_limit += RESYNCH_INC; // MOBIDEM
{
j = hc->h_resynctime;
j *= 10;
if (j == 0)
j = RESYNCH_INC;
time_limit += j;
}
hrdsp_event(hc, HRE_NORESP);
}
else
#endif
if (mComRcvChar(hCom, &rcode) == 0)
xfer_idle(hc->hSession);
else if (rcode == H_MSGCHAR)
{
/* restart messages always start with #0 & use CRC */
hc->rc.expected_msg = 0;
hc->usecrc = TRUE;
mtype = ' ';
result = hr_collect_msg(hc, &mtype, &msgdata, H_CHARTIME);
if (result == HR_KBDINT)
{
if (hc->ucancel)
return(FALSE);
else
{
hr_kbdint(hc);
return(hr_cancel(hc, HRE_USRCANCEL));
}
}
else if (result == HR_LOST_CARR)
return hr_cancel(hc, HRE_LOST_CARR);
else if (result != HR_COMPLETE) /* HR_TIMEOUT or HR_BAD??? */
{
DbgOutStr("Bad message\r\n", 0,0,0,0,0);
if (mtype == 'R') /* probably our resynch, try again */
{
DbgOutStr("Bad message was type R\r\n", 0,0,0,0,0);
hrdsp_event(hc, HRE_RETRYERR);
request_again = TRUE;
}
}
else if (mtype == 'R') /* good Resynch message */
{
if (!fStarted)
hc->xfertimer = startinterval();
fStarted = TRUE;
field = strtok(msgdata, ";");
if (field == NULL || *field++ != 'R')
{
DbgOutStr("Bad format\r\n", 0,0,0,0,0);
request_again = TRUE;
hrdsp_event(hc, HRE_ILLEGAL);
}
else
{
if (unchar(*field) != (BYTE)request_tbl[tries].msgn)
{
for (i = tries - 1; i >= 0; --i)
if (unchar(*field) == (BYTE)request_tbl[i].msgn)
{
// We got a response to an earlier restart request.
// Adjust the amount of time we wait for responses
// based on the actual time of the message just
// received.
// time_limit = interval(request_tbl[i].time) +
// RESYNCH_INC; // MOBIDEM
j = hc->h_resynctime;
j *= 10;
if (j == 0)
j = RESYNCH_INC;
time_limit = interval(request_tbl[i].time) + j;
DbgOutStr("Got %d, new time_limit=%ld\r\n",
request_tbl[i].msgn, time_limit, 0,0,0);
break; /* don't ask for retry */
}
if (i < 0)
{
hrdsp_event(hc, HRE_RETRYERR);
request_again = TRUE;
DbgOutStr("Not in table\r\n", 0,0,0,0,0);
}
}
else
{
ok = TRUE;
// field = _fstrtok(NULL, FstrScolon());
field = strtok(NULL, ";");
while (field != NULL)
{
switch (*field++)
{
case 'f':
if ((int)atol(field) != hc->current_filen)
ok = FALSE;
break;
case 'o':
if (atol(field) != hc->rc.checkpoint)
ok = FALSE;
break;
case 'B':
hc->blocksize = (int)atol(field);
break;
case 'T' :
if ((i = (int)atol(field)) == 1)
hc->usecrc = FALSE;
else if (i == 2)
hc->usecrc = TRUE;
break;
default:
break;
}
// field = _fstrtok(NULL, FstrScolon());
field = strtok(NULL, ";");
}
if (ok)
{
hc->h_checksum = hc->h_crc = 0;
hc->datacnt = hc->blocksize;
if (reason != HRE_NONE || tries > 0)
hrdsp_event(hc, HRE_ERRFIXED);
hrdsp_status(hc, HRS_REC);
DbgOutStr("Resynch successful\r\n", 0,0,0,0,0);
return(TRUE);
}
else
{
hrdsp_event(hc, HRE_RETRYERR);
request_again = TRUE;
DbgOutStr("Not OK\r\n", 0,0,0,0,0);
}
}
}
}
}
}
/*lint -unreachable*/
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* hr_virus_detect
*
* DESCRIPTION:
*
*
* ARGUMENTS:
*
*
* RETURNS:
*
*/
#if FALSE
STATICF VOID _export PASCAL hr_virus_detect(VOID FAR *h, USHORT usMatchId)
{
hc->rc.virus_detected = TRUE; /* force cancel of transfer */
}
#endif
/********************** end of hpr_rcv1.c ************************/