899 lines
25 KiB
C
899 lines
25 KiB
C
/*===========================================================================*/
|
|
/* Copyright (c) 1987 - 1988, Future Soft Engineering, Inc. */
|
|
/* Houston, Texas */
|
|
/*===========================================================================*/
|
|
|
|
#define NOGDICAPMASKS TRUE
|
|
#define NOICONS TRUE
|
|
#define NOKEYSTATES TRUE
|
|
#define NOSYSCOMMANDS TRUE
|
|
#define NOATOM TRUE
|
|
#define NOCLIPBOARD TRUE
|
|
#define NODRAWTEXT TRUE
|
|
#define NOMINMAX TRUE
|
|
#define NOOPENFILE TRUE
|
|
#define NOSCROLL TRUE
|
|
#define NOHELP TRUE
|
|
#define NOPROFILER TRUE
|
|
#define NODEFERWINDOWPOS TRUE
|
|
#define NOPEN TRUE
|
|
#define NO_TASK_DEFINES TRUE
|
|
#define NOLSTRING TRUE
|
|
#define USECOMM
|
|
|
|
#include <stdarg.h>
|
|
#include <windows.h>
|
|
#include <port1632.h>
|
|
#include "dcrc.h"
|
|
#include "dynacomm.h"
|
|
#include "task.h"
|
|
#include "connect.h"
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* mdmConnect() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* NOTE: PATCH until WIN COMM DRV is fixed!!! */
|
|
|
|
#define DEB_MSR_OFFSET 35 /* mbbx 1.10: carrier... */
|
|
#define DEB_MSR_RLSD 0x80
|
|
|
|
BOOL mdmConnect() /* mbbx 2.00: network... */
|
|
{
|
|
BOOL bRc,bCarrier = FALSE;
|
|
// -sdj unreferenced local var: LPBYTE lpMSR;
|
|
DWORD dwModemStatus;
|
|
|
|
if(trmParams.fCarrier)
|
|
{
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMWINCOM:
|
|
DEBOUT("mdmConnect: %s\n","Calling getmodemstatus to see rlsd!");
|
|
bRc = GetCommModemStatus(sPort,&dwModemStatus);
|
|
DEBOUT("mdmConnect: rc of getmodemstatus = %lx\n",bRc);
|
|
DEBOUT("mdmConnect: dw of getmodemstatus = %lx\n",dwModemStatus);
|
|
if (!bRc)
|
|
{
|
|
DEBOUT("mdmconnect: %s\n","getmodemstatus failed, setting bCar=TRUE");
|
|
bCarrier = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bCarrier = (dwModemStatus & MS_RLSD_ON) ? TRUE : FALSE;
|
|
DEBOUT("mdmconnect: bCarrier is set as: %lx\n",bCarrier);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bCarrier = TRUE;
|
|
break;
|
|
}
|
|
|
|
if(mdmOnLine != bCarrier)
|
|
{
|
|
if(!(mdmOnLine = bCarrier))
|
|
{
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* modemReset() - Send XON character to the serial port. [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
VOID modemReset() /* mbbx 2.00: network... */
|
|
{
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMWINCOM:
|
|
switch(trmParams.flowControl)
|
|
{
|
|
case ITMXONFLOW:
|
|
DEBOUT("modemReset: Esccom(SETXON) on comport=%lx\n",sPort);
|
|
EscapeCommFunction(sPort, SETXON);
|
|
break;
|
|
case ITMHARDFLOW:
|
|
DEBOUT("modemReset: Esccom(SETRTS) on comport=%lx\n",sPort);
|
|
EscapeCommFunction(sPort, SETRTS);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
sPortErr = FALSE;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* modemBreak() - Send BREAK signal to the serial port. [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* NOTE: units for modemSendBreak are approx. 1/9 secs ( = 7 ticks) */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* VT100 standards for BREAK signals are as follows: */
|
|
/* */
|
|
/* short break: 0.233 sec = 2 units */
|
|
/* long break: 3.500 sec = 30 units */
|
|
/* */
|
|
|
|
VOID modemSendBreak(INT nCount)
|
|
{
|
|
DCB dcb; /* slc nova 051 */
|
|
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMWINCOM:
|
|
if(nCount > 2) /* slc nova 051 moved... */
|
|
{
|
|
if(GetCommState(sPort, (DCB FAR *)&dcb) == 0) /* slc nova 051 */
|
|
{
|
|
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
|
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
|
EscapeCommFunction(sPort,CLRRTS);
|
|
EscapeCommFunction(sPort,CLRDTR);
|
|
|
|
if(!SetCommState(sPort,(DCB FAR *)&dcb))
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
DEBOUT("modemSendBrk:EscapeCommFunction(sPort, SETBREAK), DelayStart..for port=%lx\n",sPort);
|
|
EscapeCommFunction(sPort, SETBREAK);
|
|
delay(nCount*7, NULL);
|
|
DEBOUT("modemSendBrk:DelayOver...EscapeCommFunction(sPort, CLRBREAK)for port=%lx\n",sPort);
|
|
EscapeCommFunction(sPort, CLRBREAK);
|
|
|
|
if(nCount > 2) /* slc nova 051 moved... */
|
|
{
|
|
if(GetCommState(sPort, (DCB FAR *)&dcb) == 0) /* slc nova 051 */
|
|
{
|
|
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
|
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
|
EscapeCommFunction(sPort,SETRTS);
|
|
EscapeCommFunction(sPort,SETDTR);
|
|
DEBOUT("modemSendBreak: set fRtsDtrdisable to false: for port=%lx\n",sPort);
|
|
if(!SetCommState(sPort,(DCB FAR *)&dcb))
|
|
{
|
|
DEBOUT("FAIL: modemSendBreak: set fRtsDtrdisable to false: for port=%lx\n",sPort);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ITMDLLCONNECT: /* rjs bug2 */
|
|
DLL_modemSendBreak(ghCCB, nCount);
|
|
break;
|
|
|
|
}/* switch */
|
|
|
|
resetSerial(&trmParams, FALSE, FALSE, 0);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* modemBytes() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
VOID NEAR WIN_modemBytes() /* mbbx 2.00: network... */
|
|
{
|
|
// -sdj unreferenced local var: INT i;
|
|
LPBYTE ltmp;
|
|
COMSTAT serInfo;
|
|
DWORD dwErrors;
|
|
DWORD dwBytesRead;
|
|
OVERLAPPED overlap;
|
|
BOOL bRc;
|
|
|
|
overlap.hEvent = overlapEvent;
|
|
overlap.Internal = 0;
|
|
overlap.InternalHigh = 0;
|
|
overlap.Offset = 0;
|
|
overlap.OffsetHigh = 0;
|
|
|
|
ResetEvent(overlapEvent);
|
|
|
|
gotCommEvent = FALSE;
|
|
|
|
bRc = ReadFile(sPort, serBytes+1, LOCALMODEMBUFSZ-1,
|
|
(LPDWORD)&serCount, (LPOVERLAPPED)&overlap);
|
|
|
|
if(!bRc && ((dwErrors = GetLastError()) != ERROR_IO_PENDING))
|
|
{
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo); /* reset after error */
|
|
|
|
if(trmParams.flowControl == ITMHARDFLOW)
|
|
{
|
|
if(serInfo.cbInQue < 100)
|
|
{
|
|
modemReset();
|
|
}
|
|
}
|
|
|
|
if(serInfo.fXoffSent || serInfo.fCtsHold || serInfo.fDsrHold)
|
|
{
|
|
if(serInfo.cbInQue < 100)
|
|
{
|
|
modemReset();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!bRc && ((dwErrors = GetLastError()) == ERROR_IO_PENDING))
|
|
{
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo);
|
|
}
|
|
|
|
if(!GetOverlappedResult(sPort, &overlap, &dwBytesRead, FALSE))
|
|
return;
|
|
|
|
if(serCount = dwBytesRead)
|
|
{
|
|
ltmp = serBytes+1;
|
|
|
|
if(serCount != LOCALMODEMBUFSZ-1)
|
|
{
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo); /* reset after error */
|
|
|
|
if(trmParams.flowControl == ITMHARDFLOW) /* rjs bug2 003 */
|
|
{
|
|
if(serInfo.cbInQue < 100)
|
|
{
|
|
modemReset();
|
|
}
|
|
}
|
|
|
|
if(serInfo.fXoffSent || serInfo.fCtsHold || serInfo.fDsrHold)
|
|
{
|
|
if(serInfo.cbInQue < 100)
|
|
{
|
|
modemReset();
|
|
}
|
|
}
|
|
} /* if readfile cameout halfway through */
|
|
else
|
|
{
|
|
gotCommEvent = TRUE; /* we read a full buffer, try again..*/
|
|
}
|
|
|
|
}
|
|
} /* readfile succeded lets see the bytes read */
|
|
}
|
|
|
|
|
|
INT modemBytes() /* mbbx 2.00: network... */
|
|
{
|
|
LPCONNECTOR_CONTROL_BLOCK lpCCB; /* slc nova 031 */
|
|
BYTE tmp1[TMPNSTR+1];
|
|
BYTE tmp2[TMPNSTR+1];
|
|
|
|
|
|
|
|
if(serNdx > 0)
|
|
return(serCount - (serNdx-1));
|
|
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMWINCOM:
|
|
|
|
|
|
//-sdj comments from checkcommevent():
|
|
//-sdj for telnet-quit processing
|
|
//-sdj if this is a telnet connection which was opened before and
|
|
//-sdj the user hits cntl-c/bye/quit etc
|
|
//-sdj the telnet service will stop talking
|
|
//-sdj with us, but terminalapp still keeps
|
|
//-sdj doing io without knowing that the handle
|
|
//-sdj can only be closed now, The way we can
|
|
//-sdj detect this is, to check if getlasterror
|
|
//-sdj is ERROR_NETNAME_DELETED, if this is the
|
|
//-sdj case then we should do exactly same thing
|
|
//-sdj which we do when the user tries to go to
|
|
//-sdj some other comm port, close this one, and
|
|
//-sdj go to the next one.
|
|
//-sdj by setting bPortDisconnected to TRUE,
|
|
//-sdj further modemBytes()[reads] will stop on
|
|
//-sdj this port, and modemBytes will prompt the
|
|
//-sdj user to select some other port, and return.
|
|
|
|
|
|
if (bPortDisconnected)
|
|
{
|
|
LoadString(hInst, STR_PORTDISCONNECT, (LPSTR) tmp1, TMPNSTR);
|
|
LoadString(hInst, STR_ERRCAPTION, (LPSTR) tmp2, TMPNSTR);
|
|
MessageBox(hItWnd, (LPSTR) tmp1, (LPSTR)tmp2, MB_OK | MB_APPLMODAL);
|
|
serCount = 0; //so that return dword is 0, no chars to process
|
|
// resetSerial(&trmParams, FALSE,TRUE,0);
|
|
if(!trmParams.fResetDevice)
|
|
trmParams.newDevRef = trmParams.comDevRef;
|
|
exitSerial();
|
|
doSettings(IDDBCOMM, dbComm);
|
|
break;
|
|
}
|
|
|
|
if(gotCommEvent)
|
|
{
|
|
WIN_modemBytes();
|
|
}
|
|
else
|
|
serCount = 0;
|
|
|
|
break;
|
|
|
|
case ITMDLLCONNECT: /* slc nova 012 bjw nova 002 */
|
|
serCount = DLL_ConnectBytes(ghCCB); /* slc nova 031 */
|
|
if((lpCCB = (LPCONNECTOR_CONTROL_BLOCK)GlobalLock(ghCCB)) != NULL) /* slc nova 031 */
|
|
{
|
|
if(serCount == CONNECT_READ_ERROR)
|
|
serCount = lpCCB->wReadBufferRead;
|
|
|
|
lmovmem((LPSTR)lpCCB->lpReadBuffer, (LPSTR)(serBytes + 1), (WORD)serCount);
|
|
GlobalUnlock(ghCCB);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(serCount > 0)
|
|
serNdx = 1; /* indicates chars to process */
|
|
|
|
return(serCount);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* getMdmChar() - Get a modem character out of local buffer. [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* NOTE: modemBytes() must be called prior to this routine */
|
|
|
|
BYTE getMdmChar(BOOL bText)
|
|
{
|
|
BYTE nextChar;
|
|
|
|
nextChar = serBytes[serNdx++];
|
|
if(serNdx > serCount)
|
|
serNdx = 0;
|
|
|
|
if(trmParams.parity != ITMNOPARITY)
|
|
nextChar &= 0x7F;
|
|
|
|
if(bText && (trmParams.language > ICS_NONE) && (termState == NULL)) /* mbbx 1.06A: ics new xlate... */
|
|
{
|
|
if(nextChar >= 0x80) /* slc swat */
|
|
{
|
|
if(trmParams.setIBMXANSI)
|
|
nextChar = ansiXlateTable[nextChar]; /* IBM extended to ANSI */
|
|
}
|
|
else
|
|
{
|
|
if(trmParams.language > ICS_NONE)
|
|
nextChar = icsXlateTable[nextChar]; /* ISO char to ANSI */
|
|
}
|
|
}
|
|
|
|
return(nextChar);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* getRcvChar() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
BOOL getRcvChar(BYTE *theChar, BYTE charMask)
|
|
{
|
|
if(modemBytes())
|
|
{
|
|
*theChar = getMdmChar(FALSE);
|
|
|
|
if(charMask != 0)
|
|
*theChar &= charMask;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
*theChar = 0;
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* waitRcvChar() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
BOOL waitRcvChar(BYTE *theChar, WORD timeOut, BYTE charMask, BYTE charFirst, ...)
|
|
{
|
|
va_list ap;
|
|
DWORD waitTicks; //-sdj was LONG, getcurrenttime,tickcount returns dword
|
|
//-sdj this was causing a sign/unsign warning noise
|
|
BYTE charList;
|
|
|
|
waitTicks = tickCount() + (timeOut * 6);
|
|
repeat
|
|
{
|
|
va_start(ap,charFirst);
|
|
updateTimer();
|
|
|
|
if(doneFlag)
|
|
{
|
|
xferStopped = TRUE;
|
|
va_end(ap);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(xferStopped)
|
|
break;
|
|
|
|
gotCommEvent = TRUE;
|
|
|
|
if(getRcvChar(theChar, charMask))
|
|
{
|
|
|
|
if(charFirst == 0)
|
|
{
|
|
va_end(ap);
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
for(charList = charFirst; charList != 0; charList = va_arg(ap,BYTE))
|
|
{
|
|
if(charList == *theChar)
|
|
{
|
|
va_end(ap);
|
|
return(TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
*theChar = 0;
|
|
}
|
|
|
|
//if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
// mainEventLoop();
|
|
//sdj: now that rcv and snd b file are threads the main
|
|
//sdj: thread will deal with UI while the xfer is going on, so
|
|
//sdj: no need of this hack to peek the msges.
|
|
//sdj: but lets put sleep of 10ms so that we dont hog the CPU
|
|
//sdj: and give chance for the buffer to fill and reduce number
|
|
//sdj: of calls to ReadFile()
|
|
|
|
Sleep(10);
|
|
|
|
}
|
|
until(tickCount() >= waitTicks);
|
|
|
|
va_end(ap);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* flushRBuf() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
VOID flushRBuff()
|
|
{
|
|
if(modemBytes())
|
|
delay(6, NULL); /* mbbx: wtf??? */
|
|
|
|
while(modemBytes())
|
|
serNdx = 0; /* mbbx: dump serBytes data */
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* checkUserAbort() - [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
BOOL checkUserAbort()
|
|
{
|
|
BOOL checkUserAbort = FALSE;
|
|
|
|
return(FALSE);
|
|
|
|
if(PeekMessage(&msg, hdbXferCtrls, 0, 0, PM_REMOVE))
|
|
{
|
|
if((msg.hwnd != xferCtlStop) ||
|
|
(msg.message < WM_MOUSEFIRST) ||
|
|
(msg.message > WM_MOUSELAST))
|
|
{
|
|
IsDialogMessage(hdbXferCtrls, &msg);
|
|
}
|
|
}
|
|
|
|
while(PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
|
|
{
|
|
if((msg.message == WM_KEYDOWN) && (msg.wParam == VK_CANCEL))
|
|
checkUserAbort = TRUE;
|
|
}
|
|
|
|
return(checkUserAbort);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* modemWrite() - Send data to comm port (no special processing here) [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
BOOL NEAR WIN_modemWrite(LPSTR lpData, INT nSize)
|
|
{
|
|
BOOL modemWrite = TRUE;
|
|
BOOL bWriteFile;
|
|
INT nRemain;
|
|
INT nBytes;
|
|
INT nSent;
|
|
COMSTAT serInfo;
|
|
// -sdj unreferenced local var: BYTE str[80];
|
|
DWORD dwErrors;
|
|
OVERLAPPED overlap;
|
|
BOOL bRc;
|
|
|
|
overlap.hEvent = overlapEvent;
|
|
overlap.Internal = 0;
|
|
overlap.InternalHigh = 0;
|
|
overlap.Offset = 0;
|
|
overlap.OffsetHigh = 0;
|
|
|
|
for(nRemain = nSize; nRemain > 0; nRemain -= nSent)
|
|
{
|
|
nBytes = nRemain;
|
|
|
|
bWriteFile = WriteFile(sPort, (LPVOID) (lpData+(nSize-nRemain)),
|
|
nBytes, (LPDWORD) &nSent,
|
|
(LPOVERLAPPED)&overlap);
|
|
|
|
dwErrors = GetLastError();
|
|
|
|
if ((!bWriteFile) && (dwErrors != ERROR_IO_PENDING))
|
|
{
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo);
|
|
|
|
if(serInfo.fXoffSent || serInfo.fCtsHold)
|
|
{
|
|
if(serInfo.fCtsHold)
|
|
{
|
|
sPortErr = TRUE;
|
|
return(FALSE);
|
|
}
|
|
|
|
rxEventLoop(); /* jtf 3.20 */
|
|
|
|
if ( (xferStopped == TRUE) && (xferFlag != XFRNONE) ) /* jtf 3.33 3.30 */
|
|
{
|
|
modemWrite = TRUE;
|
|
return(modemWrite); /* jtf 3.30 */
|
|
}
|
|
|
|
if(checkUserAbort()) /* mbbx: see if CTRL BREAK hit */
|
|
{
|
|
switch(trmParams.flowControl) /* mbbx 1.10: CUA... */
|
|
{
|
|
case ITMXONFLOW:
|
|
modemReset();
|
|
break;
|
|
|
|
case ITMHARDFLOW: /* drastic ... */
|
|
trmParams.flowControl = ITMNOFLOW;
|
|
resetSerial(&trmParams, FALSE, FALSE, 0);
|
|
break;
|
|
}
|
|
modemWrite = FALSE;
|
|
break;
|
|
}/* if checkUserAbort */
|
|
}/* if serInfo.hold */
|
|
}/* if writeComm */
|
|
else
|
|
{
|
|
if(!bWriteFile)
|
|
if(dwErrors != ERROR_IO_PENDING)
|
|
{
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo);
|
|
modemWrite = FALSE;
|
|
nSent = 0;
|
|
}
|
|
else
|
|
{
|
|
if(WaitForSingleObject(overlapEvent, dwWriteFileTimeout) == 0)
|
|
{
|
|
GetOverlappedResult(sPort, &overlap, (LPDWORD)&nSent, TRUE);
|
|
}
|
|
else
|
|
{
|
|
ResetEvent(overlapEvent);
|
|
bRc = ClearCommError(sPort, &dwErrors, &serInfo);
|
|
nSent = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef SLEEP_FOR_CONTEXT_SWITCH
|
|
|
|
Sleep((DWORD)5);
|
|
#endif
|
|
|
|
// if(!nSent)
|
|
// {
|
|
// modemWrite = FALSE;
|
|
// break;
|
|
// }
|
|
}
|
|
}/* for */
|
|
|
|
if(xferBreak) /* mbbx 2.00: xfer ctrls... */
|
|
{
|
|
setXferCtrlButton(IDSTOP, STR_STOP);
|
|
xferBreak = FALSE;
|
|
}
|
|
|
|
return(modemWrite);
|
|
}/* WIN_modemWrite */
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
|
|
BOOL modemWrite(LPSTR lpData, INT nSize)
|
|
{
|
|
LPCONNECTOR_CONTROL_BLOCK lpCCB; /* slc nova 031 */
|
|
BOOL bResult = FALSE; /* slc swat */
|
|
|
|
if (nSize == 0) /* mbbx 2.00.04: check outgoing buffer... */
|
|
{
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMDLLCONNECT: /* slc nova 028 */
|
|
if((lpCCB = (LPCONNECTOR_CONTROL_BLOCK)GlobalLock(ghCCB)) != NULL)
|
|
{
|
|
lpCCB->wWriteBufferUsed = (WORD)nSize; /* slc nova 031 */
|
|
GlobalUnlock(ghCCB);
|
|
DLL_WriteConnector(ghCCB);
|
|
}
|
|
break;
|
|
case ITMWINCOM:
|
|
default:
|
|
break;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/* We cannot allow recursive calls to the modemWrite() sub,
|
|
cuz we stack overflow! Design issue: caller should check
|
|
this return value and re-call with same data!
|
|
*/
|
|
|
|
if(bgOutStandingWrite) /* slc swat */
|
|
{
|
|
sysBeep();
|
|
return(FALSE);
|
|
}
|
|
else
|
|
bgOutStandingWrite = TRUE;
|
|
|
|
|
|
switch(trmParams.comDevRef)
|
|
{
|
|
case ITMWINCOM:
|
|
bResult = WIN_modemWrite(lpData, nSize);
|
|
break;
|
|
|
|
case ITMDLLCONNECT: /* slc nova 012 bjw nova 002 */
|
|
if((lpCCB = (LPCONNECTOR_CONTROL_BLOCK)GlobalLock(ghCCB)) != NULL) /* slc nova 031 */
|
|
{
|
|
if(lpCCB->lpWriteBuffer) /* seh nova 005 */
|
|
{
|
|
lmovmem((LPSTR)lpData, (LPSTR)lpCCB->lpWriteBuffer, (WORD)nSize); /* seh nova 005 */
|
|
lpCCB->wWriteBufferUsed = (WORD)nSize; /* seh nova 005 */
|
|
|
|
GlobalUnlock(ghCCB); /* slc nova 031 */
|
|
bResult = DLL_WriteConnector(ghCCB);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}/* switch */
|
|
|
|
bgOutStandingWrite = FALSE; /* slc swat */
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* modemWr() - Send character to the windows serial port driver. [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
VOID modemWr(BYTE theByte)
|
|
{
|
|
BYTE saveByte = theByte;
|
|
BYTE ISOByte;
|
|
|
|
if((theByte >= 0x80) && (xferFlag < XFRBSND)) /* mbbx 1.10: VT220 8BIT... */
|
|
{
|
|
if(trmParams.language > ICS_NONE)
|
|
ISOByte = icsXlateTable[theByte];
|
|
else
|
|
ISOByte = theByte;
|
|
|
|
if(trmParams.setIBMXANSI)
|
|
{
|
|
if(ISOByte >= 0x80) /* was not ISO */
|
|
theByte = ansiXlateTable[theByte & 0x7F]; /* ANSI to IBM extended */
|
|
}
|
|
else
|
|
theByte = ISOByte;
|
|
}
|
|
else if((theByte == CR) && (trmParams.emulate == ITMDELTA))
|
|
theByte = XOFF;
|
|
|
|
if(!modemWrite((LPSTR) &theByte, 1))
|
|
return;
|
|
|
|
if(trmParams.localEcho && (xferFlag < XFRTYP))
|
|
{
|
|
modemInp(saveByte, FALSE);
|
|
if((theByte == CR) && (xferFlag == XFRSND))
|
|
modemInp(LF, FALSE);
|
|
}
|
|
|
|
if(trmParams.outCRLF && (theByte == CR) && (xferFlag == XFRNONE)) /* mbbx 2.00: heed outCRLF... */
|
|
modemWr(LF); /* yikes! it's recursive!!! */
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* termStr() - Send PASCAL character string to the modem. [mbb] */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
VOID termStr(STRING *tStr, INT nDelay, BOOL crFlag)
|
|
{
|
|
WORD ndx;
|
|
|
|
for(ndx = 1; ndx <= *tStr; ndx++)
|
|
{
|
|
modemWr(tStr[ndx]);
|
|
if(nDelay > 0)
|
|
delay(nDelay, NULL);
|
|
if(!dialing)
|
|
idleProcess();
|
|
}
|
|
|
|
if(crFlag)
|
|
modemWr(CR);
|
|
}
|
|
|
|
|
|
|
|
DWORD checkCommEvent(LPVOID lpThreadParameter)
|
|
{
|
|
DWORD eventMask;
|
|
HANDLE hEvent;
|
|
OVERLAPPED OverLapped;
|
|
DWORD dwGetLastError;
|
|
|
|
// eventMask = EV_RXCHAR | EV_ERR | EV_BREAK | EV_CTS | EV_DSR;
|
|
eventMask = EV_RXCHAR;
|
|
SetCommMask(sPort, eventMask);
|
|
|
|
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
OverLapped.hEvent = hEvent;
|
|
|
|
while(TRUE)
|
|
{
|
|
if(bPortIsGood && (sPort != NULL) && (sPort != (HANDLE)-1) && (!CommThreadExit) )
|
|
{
|
|
if(WaitForSingleObject(hMutex, 50) == 0)
|
|
{
|
|
eventMask = EV_RXCHAR;
|
|
// SetCommMask(sPort, eventMask);
|
|
|
|
if(WaitCommEvent(sPort, (LPDWORD)&eventMask, &OverLapped))
|
|
{
|
|
gotCommEvent = TRUE;
|
|
}
|
|
else
|
|
{
|
|
dwGetLastError = GetLastError();
|
|
if (dwGetLastError == ERROR_IO_PENDING)
|
|
{
|
|
|
|
DWORD Trash;
|
|
GetOverlappedResult(
|
|
sPort,
|
|
&OverLapped,
|
|
&Trash,
|
|
TRUE
|
|
);
|
|
gotCommEvent = TRUE;
|
|
|
|
}
|
|
else {
|
|
|
|
//-sdj for telnet-quit processing
|
|
//-sdj if this is a telnet connection and
|
|
//-sdj the user hits cntl-c/bye/quit etc
|
|
//-sdj the telnet service will stop talking
|
|
//-sdj with us, but terminalapp still keeps
|
|
//-sdj doing io without knowing that the handle
|
|
//-sdj can only be close now, The way we can
|
|
//-sdj detect this is, to check if getlasterror
|
|
//-sdj is ERROR_NETNAME_DELETED, if this is the
|
|
//-sdj case then we should do exactly same thing
|
|
//-sdj which we do when the user tries to go to
|
|
//-sdj some other comm port, close this one, and
|
|
//-sdj go to the next one.
|
|
//-sdj by setting bPortDisconnected to TRUE,
|
|
//-sdj further modemBytes()[reads] will stop on
|
|
//-sdj this port, and modemBytes will prompt the
|
|
//-sdj user to select some other port, and return.
|
|
|
|
CloseHandle(sPort); // only valid operation in this state
|
|
sPort = NULL; // this will prevent checkcommevent to
|
|
// attempt unnecessary waits untill sPort
|
|
// becomes valid, and bPortDisconnected
|
|
// is set back to FALSE by modembytes/resetserial
|
|
|
|
bPortDisconnected = TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if(CommThreadExit) // was ,doneFlag but doneFlag
|
|
// does not get set for sometime
|
|
// even after the comm port closes
|
|
// so exit the thread when you know
|
|
// that the port is going to get closed
|
|
// This flag is init to false and set
|
|
// to true just before calling exitserial
|
|
// in termfile.c
|
|
|
|
{
|
|
gbThreadDoneFlag = TRUE;
|
|
ReleaseMutex(hMutex);
|
|
ResetEvent(hEvent);
|
|
ExitThread((DWORD)0);
|
|
}
|
|
|
|
ReleaseMutex(hMutex);
|
|
|
|
eventMask = EV_RXCHAR;
|
|
} // wait on mutex
|
|
|
|
#ifdef SLEEP_FOR_CONTEXT_SWITCH
|
|
|
|
Sleep((DWORD)3);
|
|
#endif
|
|
|
|
|
|
ResetEvent(hEvent);
|
|
} // good sPort
|
|
else
|
|
{
|
|
if(CommThreadExit) // was doneFlag : see above for comments
|
|
{
|
|
gbThreadDoneFlag = TRUE;
|
|
ReleaseMutex(hMutex);
|
|
ResetEvent(hEvent);
|
|
ExitThread((DWORD)0);
|
|
}
|
|
|
|
Sleep((DWORD)3); // -sdj either the comm port handle is changing
|
|
// or it is invalid, so instead of doing
|
|
// a tight while-true, sleep each time you
|
|
// come here, so that others get a chance
|
|
|
|
}
|
|
}
|
|
return 0;
|
|
}
|