mirror of https://github.com/tongzx/nt5src
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.
871 lines
27 KiB
871 lines
27 KiB
/***************************************************************************
|
|
Name : fdebug.C
|
|
Comment : Factored out debug code
|
|
Functions : (see Prototypes just below)
|
|
|
|
Copyright (c) Microsoft Corp. 1991, 1992, 1993
|
|
|
|
Revision Log
|
|
Num Date Name Description
|
|
--- -------- ---------- -----------------------------------------------
|
|
***************************************************************************/
|
|
|
|
#include "prep.h"
|
|
|
|
#include <comdevi.h>
|
|
|
|
#ifndef MDDI
|
|
# include "filet30.h" //RSL just need t30fail.h
|
|
# include "efaxcb.h"
|
|
#endif //MDDI
|
|
|
|
|
|
|
|
#include "fcomapi.h"
|
|
#include "fcomint.h"
|
|
#include "fdebug.h"
|
|
|
|
|
|
#include "glbproto.h"
|
|
|
|
|
|
#define faxTlog(m) DEBUGMSG(ZONE_DB, m)
|
|
#define faxT3log(m) DEBUGMSG(ZONE_DB3, m)
|
|
#define FILEID FILEID_FDEBUG
|
|
|
|
#ifdef DEBUG
|
|
# define ST_DB(x) if(ZONE_DB) { x; }
|
|
# define ST_DB3(x) if(ZONE_DB3) { x; }
|
|
#else
|
|
# define ST_DB(x) { }
|
|
# define ST_DB3(x) { }
|
|
#endif
|
|
|
|
#define FLUSHBUFSIZE 256
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void InitCommErrCount(PThrdGlbl pTG)
|
|
{
|
|
#ifndef MDDI
|
|
T30FAILURECODE err;
|
|
|
|
err = 0;
|
|
if(pTG->Comm.uOtherErrorCount >= 20)
|
|
err = T30FAIL_OTHERCOMM2;
|
|
else if(pTG->Comm.uOtherErrorCount >= 10)
|
|
err = T30FAIL_OTHERCOMM1;
|
|
else if(pTG->Comm.uOtherErrorCount >= 5)
|
|
err = T30FAIL_OTHERCOMM;
|
|
if(err)
|
|
ICommFailureCode(pTG, err);
|
|
|
|
err = 0;
|
|
if(pTG->Comm.uFramingBreakErrorCount >= 20)
|
|
err = T30FAIL_FRAMING2;
|
|
else if(pTG->Comm.uFramingBreakErrorCount >= 10)
|
|
err = T30FAIL_FRAMING1;
|
|
else if(pTG->Comm.uFramingBreakErrorCount >= 5)
|
|
err = T30FAIL_FRAMING;
|
|
if(err)
|
|
ICommFailureCode(pTG, err);
|
|
|
|
err = 0;
|
|
if(pTG->Comm.uBufferOverflowCount >= 20)
|
|
err = T30FAIL_BUFOVER2;
|
|
else if(pTG->Comm.uBufferOverflowCount >= 10)
|
|
err = T30FAIL_BUFOVER1;
|
|
else if(pTG->Comm.uBufferOverflowCount >= 5)
|
|
err = T30FAIL_BUFOVER;
|
|
if(err)
|
|
ICommFailureCode(pTG, err);
|
|
|
|
err = 0;
|
|
if(pTG->Comm.uInterruptOverunCount >= 20)
|
|
err = T30FAIL_OVER2;
|
|
else if(pTG->Comm.uInterruptOverunCount >= 10)
|
|
err = T30FAIL_OVER1;
|
|
else if(pTG->Comm.uInterruptOverunCount >= 5)
|
|
err = T30FAIL_OVER;
|
|
if(err)
|
|
ICommFailureCode(pTG, err);
|
|
#endif //MDDI
|
|
|
|
pTG->Comm.uInterruptOverunCount = 0;
|
|
pTG->Comm.uBufferOverflowCount = 0;
|
|
pTG->Comm.uFramingBreakErrorCount= 0;
|
|
pTG->Comm.uOtherErrorCount = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void far D_GotError(PThrdGlbl pTG, LONG_PTR nCid, int err, COMSTAT far* lpcs)
|
|
{
|
|
// int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
|
|
|
|
if(err & CE_OVERRUN)
|
|
pTG->Comm.uInterruptOverunCount++;
|
|
if(err & CE_RXOVER)
|
|
pTG->Comm.uBufferOverflowCount++;
|
|
if(err & (CE_BREAK | CE_FRAME))
|
|
pTG->Comm.uFramingBreakErrorCount++;
|
|
if(err & (~(CE_OVERRUN | CE_RXOVER | CE_BREAK | CE_FRAME)))
|
|
pTG->Comm.uOtherErrorCount++;
|
|
|
|
#ifdef DEBUG
|
|
BG_CHK(err);
|
|
D_PrintCE(err);
|
|
|
|
D_PrintCOMSTAT(pTG, lpcs);
|
|
|
|
// .... won't work in Win32.....
|
|
// MyGetCommEvent(nCid, &nCommEvt);
|
|
// Just get the events. Clears events according to mask.
|
|
// Here NONE cleared. Avoid side effects.
|
|
// D_PrintEvent(nCommEvt);
|
|
#endif // DEBUG
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void far D_FComPrint(PThrdGlbl pTG, LONG_PTR nCid)
|
|
{
|
|
#ifdef DEBUG
|
|
// int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
|
|
COMSTAT comstat;
|
|
int err; // _must_ be 32bits in Win32
|
|
|
|
GetCommErrorNT( pTG, (HANDLE) nCid, &err, &comstat);
|
|
D_PrintCE(err);
|
|
D_PrintCOMSTAT(pTG, &comstat);
|
|
// .... won't work in Win32.....
|
|
// MyGetCommEvent(nCid, &nCommEvt);
|
|
// D_PrintEvent(nCommEvt);
|
|
#endif
|
|
}
|
|
|
|
void far D_HexPrint(LPB b1, UWORD incnt)
|
|
{
|
|
#ifdef DEBUG
|
|
BYTE b2[FLUSHBUFSIZE];
|
|
UWORD i, j;
|
|
|
|
faxTlog(("In D_HexPrint: b1=0x%08lx incnt=%d\r\n", (LPSTR)b1, incnt));
|
|
|
|
for(i=0; i<incnt;)
|
|
{
|
|
for(j=0; i<incnt && j<FLUSHBUFSIZE-6;)
|
|
{
|
|
j += (UWORD)wsprintf(b2+j, "%02x ", (UWORD)(b1[i]));
|
|
i++;
|
|
}
|
|
b2[j] = 0;
|
|
TRACE(("[ %s]\r\n", (LPSTR)b2));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_PrintIE(int err)
|
|
{
|
|
switch(err)
|
|
{
|
|
case IE_BADID: ERRMSG(("<<ERROR>> IE(%02x) Some Bad Com identifier\r\n", err)); break;
|
|
case IE_BAUDRATE: ERRMSG(("<<ERROR>> IE(%02x) Bad Baud Rate\r\n", err)); break;
|
|
case IE_BYTESIZE: ERRMSG(("<<ERROR>> IE(%02x) Invalid Byte Size\r\n", err)); break;
|
|
case IE_DEFAULT: ERRMSG(("<<ERROR>> IE(%02x) Error in default params\r\n", err)); break;
|
|
case IE_HARDWARE: ERRMSG(("<<ERROR>> IE(%02x) Missing Hardware\r\n", err)); break;
|
|
case IE_MEMORY: ERRMSG(("<<ERROR>> IE(%02x) Can't get memory\r\n", err)); break;
|
|
case IE_NOPEN: ERRMSG(("<<ERROR>> IE(%02x) Device not open\r\n", err)); break;
|
|
case IE_OPEN: ERRMSG(("<<ERROR>> IE(%02x) Device already open\r\n", err)); break;
|
|
default: ERRMSG(("<<ERROR>> IE(%02x) No Comm Error!!!!\r\n", err)); break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_PrintCE(int err)
|
|
{
|
|
if(err & CE_MODE)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) CE Mode -- or nCid is illegal\r\n", err));
|
|
return;
|
|
}
|
|
if(err & CE_RXOVER)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Receive Buffer Overflow\r\n", err));
|
|
}
|
|
if(err & CE_OVERRUN)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Receive Overrun (not an error during startup) \r\n", err));
|
|
}
|
|
if(err & CE_RXPARITY)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Receive Parity error\r\n", err));
|
|
}
|
|
if(err & CE_FRAME)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Framing error (not an error during call startup or shutdown)\r\n", err));
|
|
}
|
|
if(err & CE_BREAK)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Break condition (not an error during call startup or shutdown) \r\n", err));
|
|
}
|
|
if(err & CE_TXFULL)
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Transmit Buffer full\r\n", err));
|
|
}
|
|
if(err & (CE_PTO | CE_IOE | CE_DNS | CE_OOP))
|
|
{
|
|
ERRMSG(("<<ERROR>> CE(%02x) Parallel Printer Errors!!!\r\n", err));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_PrintCOMSTAT(PThrdGlbl pTG, COMSTAT far* lpcs)
|
|
{
|
|
|
|
if((lpcs->cbInQue != pTG->PrevcbInQue) || (lpcs->cbOutQue != pTG->PrevcbOutQue) ||
|
|
(lpcs->fXoffHold != (DWORD)pTG->PrevfXoffHold) ||
|
|
(lpcs->fXoffSent != (DWORD)pTG->PrevfXoffSent))
|
|
(MyDebugPrint(pTG, LOG_ALL, "STAT::: InQ=%d PutQ=%d XoffHold=%d XoffSent=%d\r\n",
|
|
lpcs->cbInQue, lpcs->cbOutQue,
|
|
lpcs->fXoffHold, lpcs->fXoffSent));
|
|
|
|
if(lpcs->fCtsHold || lpcs->fDsrHold || lpcs->fRlsdHold || lpcs->fEof || lpcs->fTxim)
|
|
(MyDebugPrint(pTG, LOG_ALL, "???::: CTShold=%d DSRhold=%d RLShold=%d FOF=%d TXim=%d\r\n",
|
|
lpcs->fCtsHold, lpcs->fDsrHold, lpcs->fRlsdHold, lpcs->fEof, lpcs->fTxim));
|
|
|
|
pTG->PrevfXoffHold = lpcs->fXoffHold;
|
|
pTG->PrevfXoffSent = lpcs->fXoffSent;
|
|
|
|
BG_CHK(lpcs->cbInQue < 0xffff);
|
|
BG_CHK(lpcs->cbOutQue < 0xffff);
|
|
|
|
pTG->PrevcbInQue = (USHORT) lpcs->cbInQue;
|
|
pTG->PrevcbOutQue = (USHORT) lpcs->cbOutQue;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_PrintEvent(UWORD uwEvent)
|
|
{
|
|
char sz[256];
|
|
LPSTR szCurr;
|
|
|
|
szCurr = sz;
|
|
if(uwEvent & EV_RXCHAR) szCurr += wsprintf(szCurr, "1-RXCHAR ");
|
|
if(uwEvent & EV_RXFLAG) szCurr += wsprintf(szCurr, "2-RXFLAG ");
|
|
if(uwEvent & EV_TXEMPTY) szCurr += wsprintf(szCurr, "4-TXEMPTY ");
|
|
if(uwEvent & EV_CTS) szCurr += wsprintf(szCurr, "8-CTSchange ");
|
|
|
|
if(uwEvent & EV_DSR) szCurr += wsprintf(szCurr, "16-DSRchange ");
|
|
if(uwEvent & EV_RLSD) szCurr += wsprintf(szCurr, "32-CDchange ");
|
|
if(uwEvent & EV_BREAK) szCurr += wsprintf(szCurr, "64-BREAK ");
|
|
if(uwEvent & EV_ERR) szCurr += wsprintf(szCurr, "128-LSRerror ");
|
|
if(uwEvent & EV_RING) szCurr += wsprintf(szCurr, "256-RING ");
|
|
if(uwEvent & EV_PERR) szCurr += wsprintf(szCurr, "512-LPTerror ");
|
|
*szCurr = 0;
|
|
|
|
if(szCurr > sz)
|
|
faxTlog(("EVENT:::{%04x} %s\r\n", uwEvent, (LPSTR)sz));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_FComCheck(PThrdGlbl pTG, LONG_PTR nCid)
|
|
{
|
|
// int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
|
|
COMSTAT comstat;
|
|
int err; // _must_ be 32bits in Win32
|
|
|
|
GetCommErrorNT( pTG, (HANDLE) nCid, &err, &comstat);
|
|
if(err != 0)
|
|
{
|
|
D_PrintCE(err);
|
|
if(ZONE_DB)
|
|
{
|
|
D_PrintCOMSTAT(pTG, &comstat);
|
|
// .... won't work in Win32.....
|
|
// MyGetCommEvent(nCid, &nCommEvt);
|
|
// Just get the events. Clears events according to mask.
|
|
// Here NONE cleared. Avoid side effects.
|
|
// D_PrintEvent(nCommEvt);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void D_SafePrint(PThrdGlbl pTG, LPB b1, UWORD incnt)
|
|
{
|
|
BYTE b2[FLUSHBUFSIZE];
|
|
UWORD i, j;
|
|
|
|
MyDebugPrint(pTG, LOG_ALL, "In D_SafePrint: b1=0x%08lx incnt=%d\r\n", (LPSTR)b1, incnt);
|
|
|
|
for(i=0, j=0; i<incnt && j<FLUSHBUFSIZE-6; i++)
|
|
{
|
|
if(b1[i] < 32 || b1[i] >= 128)
|
|
j += (UWORD)wsprintf(b2+j, "{0x%02x}", (UWORD)(b1[i]));
|
|
else
|
|
b2[j++] = b1[i];
|
|
}
|
|
b2[j] = 0;
|
|
MyDebugPrint(pTG, LOG_ALL, "%s\r\n", (LPSTR)b2);
|
|
}
|
|
|
|
#endif //DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MON3
|
|
// COMM MONITOR CODE
|
|
// 2/11/95 JosephJ Created
|
|
//
|
|
// The functions MonInit, MonDeInit, MonPut and MonDump may be used
|
|
// to timestamp and log all reads from/writes using the comm apis.
|
|
// MonDump creates two files, one a byte buffer, and the 2nd
|
|
// an array of MONREC structures, each structure containing a timestamp
|
|
// and an offset into the first file pointing to the actual comm data.
|
|
|
|
|
|
|
|
BOOL iMonWriteFrames(PThrdGlbl pTG, HFILE hfile, ULONG_PTR dwMROffset, DWORD dwcmr);
|
|
HFILE iMonOpenAndWriteHeader(PThrdGlbl pTG);
|
|
|
|
|
|
BOOL MonInit(PThrdGlbl pTG, LPMONOPTIONS lpmo)
|
|
{
|
|
BOOL fRet=FALSE;
|
|
DWORD dwPrefMRBufSize = lpmo->dwMRBufSize;
|
|
DWORD dwPrefDataBufSize = lpmo->dwDataBufSize;
|
|
|
|
if (pTG->gMonInfo.fInited) {BG_CHK(FALSE); goto end;}
|
|
|
|
_fmemset(&pTG->gMonInfo, 0, sizeof(pTG->gMonInfo));
|
|
GetLocalTime(&pTG->gMonInfo.stStart);
|
|
pTG->gMonInfo.mo = *lpmo; //structure copy.
|
|
|
|
|
|
// Try to allocate...
|
|
|
|
#define TRYALLOC(buffer, size, minsize, maxsize, ptrtype)\
|
|
if ((size)<(minsize)) size=(minsize);\
|
|
if ((size)>(maxsize)) size=(maxsize);\
|
|
buffer = (ptrtype) MemAlloc((size));\
|
|
if (!buffer)\
|
|
{\
|
|
size = (minsize);\
|
|
buffer = (ptrtype) MemAlloc((size));\
|
|
if (!(buffer))\
|
|
{\
|
|
buffer=0;\
|
|
size=0;\
|
|
}\
|
|
}
|
|
|
|
BG_CHK(MIN_MRBUFSIZE>=sizeof(MONREC));
|
|
BG_CHK(MIN_DATABUFSIZE>=sizeof(BYTE));
|
|
TRYALLOC(pTG->gMonInfo.lpmrBuf, dwPrefMRBufSize,MIN_MRBUFSIZE,MAX_MRBUFSIZE,
|
|
LPMONREC);
|
|
if (pTG->gMonInfo.lpmrBuf)
|
|
{
|
|
TRYALLOC(pTG->gMonInfo.lpbBuf,dwPrefDataBufSize,MIN_DATABUFSIZE,MAX_DATABUFSIZE,
|
|
LPBYTE);
|
|
if (!pTG->gMonInfo.lpbBuf)
|
|
{
|
|
MemFree(pTG->gMonInfo.lpmrBuf);
|
|
pTG->gMonInfo.lpmrBuf=0;
|
|
dwPrefMRBufSize=0;
|
|
}
|
|
}
|
|
|
|
if (pTG->gMonInfo.lpmrBuf)
|
|
{
|
|
BG_CHK(dwPrefMRBufSize>=MIN_MRBUFSIZE);
|
|
BG_CHK(pTG->gMonInfo.lpbBuf);
|
|
BG_CHK(dwPrefDataBufSize>=MIN_DATABUFSIZE);
|
|
|
|
pTG->gMonInfo.lpmrNext=pTG->gMonInfo.lpmrBuf;
|
|
pTG->gMonInfo.dwcmrBuf= dwPrefMRBufSize/sizeof(MONREC);
|
|
|
|
pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf;
|
|
pTG->gMonInfo.dwcbBuf = dwPrefDataBufSize;
|
|
|
|
pTG->gMonInfo.fFreeOnExit=TRUE;
|
|
}
|
|
else
|
|
{
|
|
BG_CHK(!dwPrefMRBufSize);
|
|
BG_CHK(!pTG->gMonInfo.lpbBuf);
|
|
BG_CHK(!dwPrefDataBufSize);
|
|
|
|
pTG->gMonInfo.lpmrNext=pTG->gMonInfo.lpmrBuf=NULL;
|
|
pTG->gMonInfo.dwcmrBuf= 0;
|
|
|
|
pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf=NULL;
|
|
pTG->gMonInfo.dwcbBuf = 0;
|
|
|
|
pTG->gMonInfo.fFreeOnExit=FALSE;
|
|
fRet=FALSE;
|
|
goto end;
|
|
}
|
|
|
|
|
|
pTG->gMonInfo.fInited=TRUE;
|
|
fRet=TRUE;
|
|
|
|
end:
|
|
return fRet;
|
|
}
|
|
|
|
void MonDeInit(PThrdGlbl pTG)
|
|
{
|
|
if (!pTG->gMonInfo.fInited) { BG_CHK(FALSE); return; }
|
|
|
|
// Free monbuf and mr array, if allocated.
|
|
if (pTG->gMonInfo.fFreeOnExit)
|
|
{
|
|
MemFree(pTG->gMonInfo.lpbBuf);
|
|
MemFree(pTG->gMonInfo.lpmrBuf);
|
|
}
|
|
|
|
_fmemset(&pTG->gMonInfo, 0, sizeof(pTG->gMonInfo));
|
|
}
|
|
|
|
|
|
BOOL MonPutComm(PThrdGlbl pTG, WORD wFlags, LPBYTE lpb, WORD wcb)
|
|
// NOTE: special wFlags value (WORD)-1 indicates that
|
|
// lpb is actually an entire MONFRAME_EVENT structure
|
|
{
|
|
DWORD cb0 = (DWORD)(pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf -
|
|
pTG->gMonInfo.lpbNext);
|
|
LPMONREC lpmrNext = pTG->gMonInfo.lpmrNext;
|
|
|
|
if ((DWORD)wcb > pTG->gMonInfo.dwcbBuf) {BG_CHK(FALSE); return FALSE;}
|
|
|
|
// +++Collapse into one bgchk after initial test.
|
|
BG_CHK(pTG->gMonInfo.fInited);
|
|
BG_CHK((pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf)>pTG->gMonInfo.lpbNext);
|
|
BG_CHK(cb0<=pTG->gMonInfo.dwcbBuf);
|
|
|
|
lpmrNext->dwTickCount=GetTickCount();
|
|
lpmrNext->wFlags=wFlags;
|
|
lpmrNext->wcb=wcb;
|
|
// even on if !wcb we still keep the offset, for consistancy.
|
|
lpmrNext->dwOffset=(DWORD)(pTG->gMonInfo.lpbNext-pTG->gMonInfo.lpbBuf);
|
|
|
|
pTG->gMonInfo.dwNumBytes+=wcb;
|
|
pTG->gMonInfo.dwNumPuts++;
|
|
|
|
pTG->gMonInfo.lpmrNext++;
|
|
if (pTG->gMonInfo.lpmrNext>=(pTG->gMonInfo.lpmrBuf+pTG->gMonInfo.dwcmrBuf))
|
|
pTG->gMonInfo.lpmrNext = pTG->gMonInfo.lpmrBuf;
|
|
if (wcb>cb0)
|
|
{
|
|
_fmemcpy(pTG->gMonInfo.lpbNext, lpb, cb0);
|
|
pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf;
|
|
wcb-=(WORD)cb0;
|
|
lpb+=cb0;
|
|
}
|
|
|
|
|
|
_fmemcpy(pTG->gMonInfo.lpbNext, lpb, wcb);
|
|
pTG->gMonInfo.lpbNext+=wcb;
|
|
if (pTG->gMonInfo.lpbNext >= (pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf))
|
|
pTG->gMonInfo.lpbNext = pTG->gMonInfo.lpbBuf;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MonPutEvent(PThrdGlbl pTG, WORD wFlags, WORD wID, WORD wSubID,
|
|
DWORD dwData0, DWORD dwData1, LPSTR lpszTxtMsg)
|
|
{
|
|
// We actually call MonPutComm, with a "special" wFlag value of
|
|
// (WORD) -1. MonDump looks for this special value and treates it
|
|
// differently when writing out the record.
|
|
|
|
|
|
char rgchBuf[sizeof(MONFRAME_EVENT)+MAX_TXTMSG_SIZE];
|
|
LPMONFRAME_EVENT lpmfe=(LPMONFRAME_EVENT) rgchBuf;
|
|
BOOL fRet=FALSE;
|
|
|
|
lpmfe->wTxtMsgOff=
|
|
lpmfe->wTotalSize=lpmfe->wHeaderSize=sizeof(MONFRAME_EVENT);
|
|
lpmfe->wcbTxtMsg = (lpszTxtMsg) ? (WORD)lstrlen(lpszTxtMsg)+1:0;
|
|
lpmfe->wTotalSize += lpmfe->wcbTxtMsg;
|
|
if (lpmfe->wTotalSize>sizeof(rgchBuf)) goto end;
|
|
lpmfe->wType = MFR_EVENT;
|
|
lpmfe->wFlags = wFlags;
|
|
lpmfe->dwTickCount = GetTickCount();
|
|
lpmfe->wID=wID;
|
|
lpmfe->wSubID=wSubID;
|
|
lpmfe->dwInstanceID=pTG->gMonInfo.dwEventInstanceID++;
|
|
lpmfe->dwData0=dwData0;
|
|
lpmfe->dwData1=dwData1;
|
|
GetLocalTime(&(lpmfe->st));
|
|
if (lpmfe->wcbTxtMsg) _fmemcpy(((LPBYTE)lpmfe)+lpmfe->wTxtMsgOff,lpszTxtMsg, lpmfe->wcbTxtMsg);
|
|
fRet = MonPutComm(pTG, (WORD)-1, (LPBYTE)lpmfe, lpmfe->wTotalSize);
|
|
|
|
end:
|
|
return fRet;
|
|
}
|
|
|
|
void MonDump(PThrdGlbl pTG)
|
|
{
|
|
HFILE hfile=HFILE_ERROR;
|
|
LPMONREC lpmrFirst;
|
|
DWORD dwcbBytesLeft;
|
|
DWORD dwNumGoodMRs;
|
|
|
|
if (!pTG->gMonInfo.fInited) {BG_CHK(FALSE); goto end;}
|
|
|
|
GetLocalTime(&pTG->gMonInfo.stDump);
|
|
|
|
hfile = iMonOpenAndWriteHeader(pTG);
|
|
|
|
if (hfile==HFILE_ERROR) goto end;
|
|
|
|
// Fixup offsets in MONREC structures to reflect the fact that
|
|
// we're going to write starting from the oldest record onwards..
|
|
//
|
|
// This is a bit tricky because some of the MONREC structures may
|
|
// not have associated data (the data could have been written over).
|
|
// There may alternatively be data for which there are no MONREC structures
|
|
// but that's OK.
|
|
//
|
|
// We start from the newest monrec structure and work our way backwards,
|
|
// checking that the data is still valid and fixing up the offsets.
|
|
|
|
if (pTG->gMonInfo.dwNumPuts<=pTG->gMonInfo.dwcmrBuf)
|
|
lpmrFirst = pTG->gMonInfo.lpmrBuf;
|
|
else
|
|
lpmrFirst = pTG->gMonInfo.lpmrNext; // MONREC buffer rollover
|
|
|
|
dwcbBytesLeft = pTG->gMonInfo.dwcbBuf; // we don't care if it's > than actually
|
|
// in buffer.
|
|
dwNumGoodMRs=0;
|
|
if (pTG->gMonInfo.dwNumPuts && pTG->gMonInfo.dwNumBytes)
|
|
{
|
|
LPMONREC lpmr = pTG->gMonInfo.lpmrNext;
|
|
|
|
// Starting with last monrec, work our way backwards...
|
|
do
|
|
{
|
|
if (lpmr>pTG->gMonInfo.lpmrBuf)
|
|
{lpmr--;}
|
|
else
|
|
{lpmr=pTG->gMonInfo.lpmrBuf+pTG->gMonInfo.dwcmrBuf-1;}
|
|
|
|
if (lpmr->wcb <= dwcbBytesLeft)
|
|
{
|
|
dwcbBytesLeft-=lpmr->wcb;
|
|
}
|
|
else
|
|
{
|
|
// we've nuked one-or-more of the earlier structures because
|
|
// their byte-data was overwritten.
|
|
// So we reset lpmrFirst to the next MR structure.
|
|
lpmrFirst=pTG->gMonInfo.lpmrBuf+
|
|
((lpmr+1-pTG->gMonInfo.lpmrBuf)%pTG->gMonInfo.dwcmrBuf);
|
|
break;
|
|
}
|
|
|
|
dwNumGoodMRs++;
|
|
|
|
} while (lpmr!=lpmrFirst);
|
|
|
|
}
|
|
|
|
iMonWriteFrames(pTG, hfile, (lpmrFirst-pTG->gMonInfo.lpmrBuf), dwNumGoodMRs);
|
|
DosClose(hfile);
|
|
|
|
|
|
pTG->gMonInfo.uRefCount++;
|
|
pTG->gMonInfo.uRefCount&=0xf; // Limit number to 16
|
|
|
|
end:
|
|
return;
|
|
}
|
|
|
|
|
|
void imon_write(HFILE hfile, LPBYTE lpb, DWORD dwcb)
|
|
{
|
|
// Write out mon file, in chunks of 32K
|
|
// -- because old mon code did that, perhaps a Win16 consideration.
|
|
#define WRITESIZE (0x1L<<15)
|
|
|
|
while(dwcb>=WRITESIZE)
|
|
{
|
|
DosWrite(hfile, lpb, WRITESIZE);
|
|
lpb+=WRITESIZE;
|
|
dwcb-=WRITESIZE;
|
|
}
|
|
if (dwcb)
|
|
{
|
|
DosWrite(hfile, lpb, dwcb);
|
|
}
|
|
}
|
|
|
|
|
|
// Create a single file which contains the combined info in the
|
|
// MONREC buffer and the byte buffer, in the form of MONFRAME
|
|
// structures.
|
|
// NOTE: special wFlags value (WORD)-1 indicates that
|
|
// lpb is actually an entire MONFRAME_EVENT structure
|
|
BOOL iMonWriteFrames(PThrdGlbl pTG, HFILE hfile, ULONG_PTR dwMROffset, DWORD dwcmr)
|
|
{
|
|
|
|
//BG_CHK((!dwMROffset && !dwcmr) || dwcmr<dwMROffset);
|
|
|
|
// Simple version: don't bother caching
|
|
{
|
|
BYTE bBuf[sizeof(MONFRAME_COMM)];
|
|
LPMONFRAME_COMM lpmfc = (LPMONFRAME_COMM) bBuf;
|
|
LPMONREC lpmr = pTG->gMonInfo.lpmrBuf+dwMROffset;
|
|
BG_CHK(dwMROffset<pTG->gMonInfo.dwcmrBuf);
|
|
BG_CHK(dwcmr<=pTG->gMonInfo.dwcmrBuf);
|
|
BG_CHK(dwcmr<=pTG->gMonInfo.dwNumPuts);
|
|
|
|
while(dwcmr--)
|
|
{
|
|
DWORD dwcb0;
|
|
BG_CHK((lpmr->wcb+sizeof(MONFRAME_COMM))<(1L<<(8*sizeof(WORD))));
|
|
BG_CHK(lpmr->wcb<=pTG->gMonInfo.dwcbBuf);
|
|
BG_CHK(lpmr->dwOffset<=pTG->gMonInfo.dwcbBuf);
|
|
if (lpmr->wFlags != (WORD)-1) // See comment at head of function
|
|
{
|
|
lpmfc->wHeaderSize = sizeof(MONFRAME_COMM);
|
|
lpmfc->wTotalSize = sizeof(MONFRAME_COMM)+lpmr->wcb;
|
|
lpmfc->wType = MFR_COMMDATA;
|
|
lpmfc->wFlags = lpmr->wFlags;
|
|
lpmfc->dwTickCount = lpmr->dwTickCount;
|
|
lpmfc->wcb = lpmr->wcb;
|
|
imon_write(hfile, (LPBYTE)lpmfc, lpmfc->wHeaderSize);
|
|
}
|
|
dwcb0=pTG->gMonInfo.dwcbBuf-lpmr->dwOffset;
|
|
if (lpmr->wcb<=dwcb0)
|
|
{
|
|
imon_write(hfile, pTG->gMonInfo.lpbBuf+lpmr->dwOffset, lpmr->wcb);
|
|
}
|
|
else
|
|
{
|
|
imon_write(hfile, pTG->gMonInfo.lpbBuf+lpmr->dwOffset, dwcb0);
|
|
imon_write(hfile, pTG->gMonInfo.lpbBuf, lpmr->wcb-dwcb0);
|
|
}
|
|
if ( (lpmr+1-pTG->gMonInfo.lpmrBuf) < (long)pTG->gMonInfo.dwcmrBuf)
|
|
lpmr++;
|
|
else
|
|
lpmr=pTG->gMonInfo.lpmrBuf;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HFILE iMonOpenAndWriteHeader(PThrdGlbl pTG)
|
|
// Open file, if it's too big, rename old file and create file again.
|
|
// If file empty, put signature
|
|
// Put introductory timestamp text event.
|
|
{
|
|
UINT uHeaderSize=0;
|
|
LPSTR lpszPathPrefix=pTG->gMonInfo.mo.rgchDir;
|
|
char rgchPath[64];
|
|
HFILE hfile = HFILE_ERROR;
|
|
LONG l=0;
|
|
|
|
if (!*lpszPathPrefix || (_fstrlen(lpszPathPrefix)+8) > sizeof (rgchPath))
|
|
{
|
|
lpszPathPrefix= "c:\\";
|
|
}
|
|
#define szMONFILESTUB "fax0"
|
|
#define szRENAMED_MONFILESTUB "old"
|
|
wsprintf(rgchPath, "%s%s", (LPSTR) lpszPathPrefix,
|
|
(LPSTR) szMONFILESTUB "." szMON_EXT);
|
|
|
|
// Try to open existing file.
|
|
hfile = DosOpen(rgchPath, OF_READWRITE|OF_SHARE_DENY_WRITE);
|
|
|
|
// Check if size is too big -- if so rename.
|
|
if (hfile!=HFILE_ERROR)
|
|
{
|
|
l = DosSeek(hfile, 0, FILE_END);
|
|
if (l==HFILE_ERROR) {DosClose(hfile); hfile=HFILE_ERROR; goto end;}
|
|
if ((DWORD)l>pTG->gMonInfo.mo.dwMaxExistingSize)
|
|
{
|
|
char rgchRenamed[64];
|
|
DosClose(hfile); hfile=HFILE_ERROR;
|
|
wsprintf(rgchRenamed, "%s%s", (LPSTR) lpszPathPrefix,
|
|
(LPSTR) szRENAMED_MONFILESTUB "." szMON_EXT);
|
|
DeleteFile(rgchRenamed);
|
|
MoveFile(rgchPath, rgchRenamed);
|
|
}
|
|
}
|
|
|
|
if (hfile== HFILE_ERROR)
|
|
{
|
|
hfile = DosCreate(rgchPath, 0);
|
|
if (hfile==HFILE_ERROR) goto end;
|
|
l=0;
|
|
}
|
|
|
|
// Write header
|
|
if (!l) {
|
|
imon_write(hfile, szMONFRM_VER001 szMONFRM_DESC001,
|
|
sizeof(szMONFRM_VER001 szMONFRM_DESC001));
|
|
}
|
|
|
|
// Create and write Text-frame with TIMESTAMP.
|
|
{
|
|
char rgchBuf[sizeof(MONFRAME_EVENT)+MAX_TXTMSG_SIZE];
|
|
LPMONFRAME_EVENT lpmfe=(LPMONFRAME_EVENT) rgchBuf;
|
|
UINT uTxtLen=0;
|
|
|
|
lpmfe->wTxtMsgOff=
|
|
lpmfe->wTotalSize=lpmfe->wHeaderSize=sizeof(MONFRAME_EVENT);
|
|
lpmfe->wType = MFR_EVENT;
|
|
lpmfe->wFlags = fEVENT_TRACELEVEL_0;
|
|
lpmfe->dwTickCount = GetTickCount();
|
|
lpmfe->wID= EVENT_ID_MON;
|
|
lpmfe->wSubID= EVENT_SubID_MON_DUMP;
|
|
lpmfe->dwInstanceID=pTG->gMonInfo.dwEventInstanceID++;
|
|
lpmfe->dwData0=0;
|
|
lpmfe->dwData1=0;
|
|
GetLocalTime(&(lpmfe->st));
|
|
|
|
uTxtLen = wsprintf(((LPBYTE)lpmfe)+lpmfe->wTxtMsgOff,
|
|
"\tStarted: %02u/%02u/%04u %02u:%02u:%02u\r\n"
|
|
"\t Puts: %lu/%lu\r\n"
|
|
"\t Bytes: %lu/%lu\r\n",
|
|
(unsigned) pTG->gMonInfo.stStart.wMonth&0xff,
|
|
(unsigned) pTG->gMonInfo.stStart.wDay&0xff,
|
|
(unsigned) pTG->gMonInfo.stStart.wYear&0xffff,
|
|
(unsigned) pTG->gMonInfo.stStart.wHour&0xff,
|
|
(unsigned) pTG->gMonInfo.stStart.wMinute&0xff,
|
|
(unsigned) pTG->gMonInfo.stStart.wSecond&0xff,
|
|
(unsigned) ((pTG->gMonInfo.dwcmrBuf>pTG->gMonInfo.dwNumPuts)
|
|
? pTG->gMonInfo.dwNumPuts: pTG->gMonInfo.dwcmrBuf),
|
|
(unsigned) pTG->gMonInfo.dwNumPuts,
|
|
(unsigned) ((pTG->gMonInfo.dwcbBuf>pTG->gMonInfo.dwNumBytes)
|
|
? pTG->gMonInfo.dwNumBytes: pTG->gMonInfo.dwcbBuf),
|
|
(unsigned) pTG->gMonInfo.dwNumBytes);
|
|
lpmfe->wcbTxtMsg = uTxtLen+1; // incuding zero.
|
|
lpmfe->wTotalSize += lpmfe->wcbTxtMsg;
|
|
BG_CHK(lpmfe->wTotalSize<=sizeof(rgchBuf));
|
|
imon_write(hfile, (LPBYTE)lpmfe, lpmfe->wTotalSize);
|
|
}
|
|
|
|
end:
|
|
return hfile;
|
|
}
|
|
#endif // MON3
|