Source code of Windows XP (NT5)
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

  1. /***************************************************************************
  2. Name : fdebug.C
  3. Comment : Factored out debug code
  4. Functions : (see Prototypes just below)
  5. Copyright (c) Microsoft Corp. 1991, 1992, 1993
  6. Revision Log
  7. Num Date Name Description
  8. --- -------- ---------- -----------------------------------------------
  9. ***************************************************************************/
  10. #include "prep.h"
  11. #include <comdevi.h>
  12. #ifndef MDDI
  13. # include "filet30.h" //RSL just need t30fail.h
  14. # include "efaxcb.h"
  15. #endif //MDDI
  16. #include "fcomapi.h"
  17. #include "fcomint.h"
  18. #include "fdebug.h"
  19. #include "glbproto.h"
  20. #define faxTlog(m) DEBUGMSG(ZONE_DB, m)
  21. #define faxT3log(m) DEBUGMSG(ZONE_DB3, m)
  22. #define FILEID FILEID_FDEBUG
  23. #ifdef DEBUG
  24. # define ST_DB(x) if(ZONE_DB) { x; }
  25. # define ST_DB3(x) if(ZONE_DB3) { x; }
  26. #else
  27. # define ST_DB(x) { }
  28. # define ST_DB3(x) { }
  29. #endif
  30. #define FLUSHBUFSIZE 256
  31. void InitCommErrCount(PThrdGlbl pTG)
  32. {
  33. #ifndef MDDI
  34. T30FAILURECODE err;
  35. err = 0;
  36. if(pTG->Comm.uOtherErrorCount >= 20)
  37. err = T30FAIL_OTHERCOMM2;
  38. else if(pTG->Comm.uOtherErrorCount >= 10)
  39. err = T30FAIL_OTHERCOMM1;
  40. else if(pTG->Comm.uOtherErrorCount >= 5)
  41. err = T30FAIL_OTHERCOMM;
  42. if(err)
  43. ICommFailureCode(pTG, err);
  44. err = 0;
  45. if(pTG->Comm.uFramingBreakErrorCount >= 20)
  46. err = T30FAIL_FRAMING2;
  47. else if(pTG->Comm.uFramingBreakErrorCount >= 10)
  48. err = T30FAIL_FRAMING1;
  49. else if(pTG->Comm.uFramingBreakErrorCount >= 5)
  50. err = T30FAIL_FRAMING;
  51. if(err)
  52. ICommFailureCode(pTG, err);
  53. err = 0;
  54. if(pTG->Comm.uBufferOverflowCount >= 20)
  55. err = T30FAIL_BUFOVER2;
  56. else if(pTG->Comm.uBufferOverflowCount >= 10)
  57. err = T30FAIL_BUFOVER1;
  58. else if(pTG->Comm.uBufferOverflowCount >= 5)
  59. err = T30FAIL_BUFOVER;
  60. if(err)
  61. ICommFailureCode(pTG, err);
  62. err = 0;
  63. if(pTG->Comm.uInterruptOverunCount >= 20)
  64. err = T30FAIL_OVER2;
  65. else if(pTG->Comm.uInterruptOverunCount >= 10)
  66. err = T30FAIL_OVER1;
  67. else if(pTG->Comm.uInterruptOverunCount >= 5)
  68. err = T30FAIL_OVER;
  69. if(err)
  70. ICommFailureCode(pTG, err);
  71. #endif //MDDI
  72. pTG->Comm.uInterruptOverunCount = 0;
  73. pTG->Comm.uBufferOverflowCount = 0;
  74. pTG->Comm.uFramingBreakErrorCount= 0;
  75. pTG->Comm.uOtherErrorCount = 0;
  76. }
  77. void far D_GotError(PThrdGlbl pTG, LONG_PTR nCid, int err, COMSTAT far* lpcs)
  78. {
  79. // int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
  80. if(err & CE_OVERRUN)
  81. pTG->Comm.uInterruptOverunCount++;
  82. if(err & CE_RXOVER)
  83. pTG->Comm.uBufferOverflowCount++;
  84. if(err & (CE_BREAK | CE_FRAME))
  85. pTG->Comm.uFramingBreakErrorCount++;
  86. if(err & (~(CE_OVERRUN | CE_RXOVER | CE_BREAK | CE_FRAME)))
  87. pTG->Comm.uOtherErrorCount++;
  88. #ifdef DEBUG
  89. BG_CHK(err);
  90. D_PrintCE(err);
  91. D_PrintCOMSTAT(pTG, lpcs);
  92. // .... won't work in Win32.....
  93. // MyGetCommEvent(nCid, &nCommEvt);
  94. // Just get the events. Clears events according to mask.
  95. // Here NONE cleared. Avoid side effects.
  96. // D_PrintEvent(nCommEvt);
  97. #endif // DEBUG
  98. }
  99. void far D_FComPrint(PThrdGlbl pTG, LONG_PTR nCid)
  100. {
  101. #ifdef DEBUG
  102. // int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
  103. COMSTAT comstat;
  104. int err; // _must_ be 32bits in Win32
  105. GetCommErrorNT( pTG, (HANDLE) nCid, &err, &comstat);
  106. D_PrintCE(err);
  107. D_PrintCOMSTAT(pTG, &comstat);
  108. // .... won't work in Win32.....
  109. // MyGetCommEvent(nCid, &nCommEvt);
  110. // D_PrintEvent(nCommEvt);
  111. #endif
  112. }
  113. void far D_HexPrint(LPB b1, UWORD incnt)
  114. {
  115. #ifdef DEBUG
  116. BYTE b2[FLUSHBUFSIZE];
  117. UWORD i, j;
  118. faxTlog(("In D_HexPrint: b1=0x%08lx incnt=%d\r\n", (LPSTR)b1, incnt));
  119. for(i=0; i<incnt;)
  120. {
  121. for(j=0; i<incnt && j<FLUSHBUFSIZE-6;)
  122. {
  123. j += (UWORD)wsprintf(b2+j, "%02x ", (UWORD)(b1[i]));
  124. i++;
  125. }
  126. b2[j] = 0;
  127. TRACE(("[ %s]\r\n", (LPSTR)b2));
  128. }
  129. #endif
  130. }
  131. #ifdef DEBUG
  132. void D_PrintIE(int err)
  133. {
  134. switch(err)
  135. {
  136. case IE_BADID: ERRMSG(("<<ERROR>> IE(%02x) Some Bad Com identifier\r\n", err)); break;
  137. case IE_BAUDRATE: ERRMSG(("<<ERROR>> IE(%02x) Bad Baud Rate\r\n", err)); break;
  138. case IE_BYTESIZE: ERRMSG(("<<ERROR>> IE(%02x) Invalid Byte Size\r\n", err)); break;
  139. case IE_DEFAULT: ERRMSG(("<<ERROR>> IE(%02x) Error in default params\r\n", err)); break;
  140. case IE_HARDWARE: ERRMSG(("<<ERROR>> IE(%02x) Missing Hardware\r\n", err)); break;
  141. case IE_MEMORY: ERRMSG(("<<ERROR>> IE(%02x) Can't get memory\r\n", err)); break;
  142. case IE_NOPEN: ERRMSG(("<<ERROR>> IE(%02x) Device not open\r\n", err)); break;
  143. case IE_OPEN: ERRMSG(("<<ERROR>> IE(%02x) Device already open\r\n", err)); break;
  144. default: ERRMSG(("<<ERROR>> IE(%02x) No Comm Error!!!!\r\n", err)); break;
  145. }
  146. }
  147. void D_PrintCE(int err)
  148. {
  149. if(err & CE_MODE)
  150. {
  151. ERRMSG(("<<ERROR>> CE(%02x) CE Mode -- or nCid is illegal\r\n", err));
  152. return;
  153. }
  154. if(err & CE_RXOVER)
  155. {
  156. ERRMSG(("<<ERROR>> CE(%02x) Receive Buffer Overflow\r\n", err));
  157. }
  158. if(err & CE_OVERRUN)
  159. {
  160. ERRMSG(("<<ERROR>> CE(%02x) Receive Overrun (not an error during startup) \r\n", err));
  161. }
  162. if(err & CE_RXPARITY)
  163. {
  164. ERRMSG(("<<ERROR>> CE(%02x) Receive Parity error\r\n", err));
  165. }
  166. if(err & CE_FRAME)
  167. {
  168. ERRMSG(("<<ERROR>> CE(%02x) Framing error (not an error during call startup or shutdown)\r\n", err));
  169. }
  170. if(err & CE_BREAK)
  171. {
  172. ERRMSG(("<<ERROR>> CE(%02x) Break condition (not an error during call startup or shutdown) \r\n", err));
  173. }
  174. if(err & CE_TXFULL)
  175. {
  176. ERRMSG(("<<ERROR>> CE(%02x) Transmit Buffer full\r\n", err));
  177. }
  178. if(err & (CE_PTO | CE_IOE | CE_DNS | CE_OOP))
  179. {
  180. ERRMSG(("<<ERROR>> CE(%02x) Parallel Printer Errors!!!\r\n", err));
  181. }
  182. }
  183. void D_PrintCOMSTAT(PThrdGlbl pTG, COMSTAT far* lpcs)
  184. {
  185. if((lpcs->cbInQue != pTG->PrevcbInQue) || (lpcs->cbOutQue != pTG->PrevcbOutQue) ||
  186. (lpcs->fXoffHold != (DWORD)pTG->PrevfXoffHold) ||
  187. (lpcs->fXoffSent != (DWORD)pTG->PrevfXoffSent))
  188. (MyDebugPrint(pTG, LOG_ALL, "STAT::: InQ=%d PutQ=%d XoffHold=%d XoffSent=%d\r\n",
  189. lpcs->cbInQue, lpcs->cbOutQue,
  190. lpcs->fXoffHold, lpcs->fXoffSent));
  191. if(lpcs->fCtsHold || lpcs->fDsrHold || lpcs->fRlsdHold || lpcs->fEof || lpcs->fTxim)
  192. (MyDebugPrint(pTG, LOG_ALL, "???::: CTShold=%d DSRhold=%d RLShold=%d FOF=%d TXim=%d\r\n",
  193. lpcs->fCtsHold, lpcs->fDsrHold, lpcs->fRlsdHold, lpcs->fEof, lpcs->fTxim));
  194. pTG->PrevfXoffHold = lpcs->fXoffHold;
  195. pTG->PrevfXoffSent = lpcs->fXoffSent;
  196. BG_CHK(lpcs->cbInQue < 0xffff);
  197. BG_CHK(lpcs->cbOutQue < 0xffff);
  198. pTG->PrevcbInQue = (USHORT) lpcs->cbInQue;
  199. pTG->PrevcbOutQue = (USHORT) lpcs->cbOutQue;
  200. }
  201. void D_PrintEvent(UWORD uwEvent)
  202. {
  203. char sz[256];
  204. LPSTR szCurr;
  205. szCurr = sz;
  206. if(uwEvent & EV_RXCHAR) szCurr += wsprintf(szCurr, "1-RXCHAR ");
  207. if(uwEvent & EV_RXFLAG) szCurr += wsprintf(szCurr, "2-RXFLAG ");
  208. if(uwEvent & EV_TXEMPTY) szCurr += wsprintf(szCurr, "4-TXEMPTY ");
  209. if(uwEvent & EV_CTS) szCurr += wsprintf(szCurr, "8-CTSchange ");
  210. if(uwEvent & EV_DSR) szCurr += wsprintf(szCurr, "16-DSRchange ");
  211. if(uwEvent & EV_RLSD) szCurr += wsprintf(szCurr, "32-CDchange ");
  212. if(uwEvent & EV_BREAK) szCurr += wsprintf(szCurr, "64-BREAK ");
  213. if(uwEvent & EV_ERR) szCurr += wsprintf(szCurr, "128-LSRerror ");
  214. if(uwEvent & EV_RING) szCurr += wsprintf(szCurr, "256-RING ");
  215. if(uwEvent & EV_PERR) szCurr += wsprintf(szCurr, "512-LPTerror ");
  216. *szCurr = 0;
  217. if(szCurr > sz)
  218. faxTlog(("EVENT:::{%04x} %s\r\n", uwEvent, (LPSTR)sz));
  219. }
  220. void D_FComCheck(PThrdGlbl pTG, LONG_PTR nCid)
  221. {
  222. // int nCommEvt; // MUST be 16bit in WIN16 and 32bit in WIN32
  223. COMSTAT comstat;
  224. int err; // _must_ be 32bits in Win32
  225. GetCommErrorNT( pTG, (HANDLE) nCid, &err, &comstat);
  226. if(err != 0)
  227. {
  228. D_PrintCE(err);
  229. if(ZONE_DB)
  230. {
  231. D_PrintCOMSTAT(pTG, &comstat);
  232. // .... won't work in Win32.....
  233. // MyGetCommEvent(nCid, &nCommEvt);
  234. // Just get the events. Clears events according to mask.
  235. // Here NONE cleared. Avoid side effects.
  236. // D_PrintEvent(nCommEvt);
  237. }
  238. }
  239. }
  240. void D_SafePrint(PThrdGlbl pTG, LPB b1, UWORD incnt)
  241. {
  242. BYTE b2[FLUSHBUFSIZE];
  243. UWORD i, j;
  244. MyDebugPrint(pTG, LOG_ALL, "In D_SafePrint: b1=0x%08lx incnt=%d\r\n", (LPSTR)b1, incnt);
  245. for(i=0, j=0; i<incnt && j<FLUSHBUFSIZE-6; i++)
  246. {
  247. if(b1[i] < 32 || b1[i] >= 128)
  248. j += (UWORD)wsprintf(b2+j, "{0x%02x}", (UWORD)(b1[i]));
  249. else
  250. b2[j++] = b1[i];
  251. }
  252. b2[j] = 0;
  253. MyDebugPrint(pTG, LOG_ALL, "%s\r\n", (LPSTR)b2);
  254. }
  255. #endif //DEBUG
  256. #ifdef MON3
  257. // COMM MONITOR CODE
  258. // 2/11/95 JosephJ Created
  259. //
  260. // The functions MonInit, MonDeInit, MonPut and MonDump may be used
  261. // to timestamp and log all reads from/writes using the comm apis.
  262. // MonDump creates two files, one a byte buffer, and the 2nd
  263. // an array of MONREC structures, each structure containing a timestamp
  264. // and an offset into the first file pointing to the actual comm data.
  265. BOOL iMonWriteFrames(PThrdGlbl pTG, HFILE hfile, ULONG_PTR dwMROffset, DWORD dwcmr);
  266. HFILE iMonOpenAndWriteHeader(PThrdGlbl pTG);
  267. BOOL MonInit(PThrdGlbl pTG, LPMONOPTIONS lpmo)
  268. {
  269. BOOL fRet=FALSE;
  270. DWORD dwPrefMRBufSize = lpmo->dwMRBufSize;
  271. DWORD dwPrefDataBufSize = lpmo->dwDataBufSize;
  272. if (pTG->gMonInfo.fInited) {BG_CHK(FALSE); goto end;}
  273. _fmemset(&pTG->gMonInfo, 0, sizeof(pTG->gMonInfo));
  274. GetLocalTime(&pTG->gMonInfo.stStart);
  275. pTG->gMonInfo.mo = *lpmo; //structure copy.
  276. // Try to allocate...
  277. #define TRYALLOC(buffer, size, minsize, maxsize, ptrtype)\
  278. if ((size)<(minsize)) size=(minsize);\
  279. if ((size)>(maxsize)) size=(maxsize);\
  280. buffer = (ptrtype) MemAlloc((size));\
  281. if (!buffer)\
  282. {\
  283. size = (minsize);\
  284. buffer = (ptrtype) MemAlloc((size));\
  285. if (!(buffer))\
  286. {\
  287. buffer=0;\
  288. size=0;\
  289. }\
  290. }
  291. BG_CHK(MIN_MRBUFSIZE>=sizeof(MONREC));
  292. BG_CHK(MIN_DATABUFSIZE>=sizeof(BYTE));
  293. TRYALLOC(pTG->gMonInfo.lpmrBuf, dwPrefMRBufSize,MIN_MRBUFSIZE,MAX_MRBUFSIZE,
  294. LPMONREC);
  295. if (pTG->gMonInfo.lpmrBuf)
  296. {
  297. TRYALLOC(pTG->gMonInfo.lpbBuf,dwPrefDataBufSize,MIN_DATABUFSIZE,MAX_DATABUFSIZE,
  298. LPBYTE);
  299. if (!pTG->gMonInfo.lpbBuf)
  300. {
  301. MemFree(pTG->gMonInfo.lpmrBuf);
  302. pTG->gMonInfo.lpmrBuf=0;
  303. dwPrefMRBufSize=0;
  304. }
  305. }
  306. if (pTG->gMonInfo.lpmrBuf)
  307. {
  308. BG_CHK(dwPrefMRBufSize>=MIN_MRBUFSIZE);
  309. BG_CHK(pTG->gMonInfo.lpbBuf);
  310. BG_CHK(dwPrefDataBufSize>=MIN_DATABUFSIZE);
  311. pTG->gMonInfo.lpmrNext=pTG->gMonInfo.lpmrBuf;
  312. pTG->gMonInfo.dwcmrBuf= dwPrefMRBufSize/sizeof(MONREC);
  313. pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf;
  314. pTG->gMonInfo.dwcbBuf = dwPrefDataBufSize;
  315. pTG->gMonInfo.fFreeOnExit=TRUE;
  316. }
  317. else
  318. {
  319. BG_CHK(!dwPrefMRBufSize);
  320. BG_CHK(!pTG->gMonInfo.lpbBuf);
  321. BG_CHK(!dwPrefDataBufSize);
  322. pTG->gMonInfo.lpmrNext=pTG->gMonInfo.lpmrBuf=NULL;
  323. pTG->gMonInfo.dwcmrBuf= 0;
  324. pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf=NULL;
  325. pTG->gMonInfo.dwcbBuf = 0;
  326. pTG->gMonInfo.fFreeOnExit=FALSE;
  327. fRet=FALSE;
  328. goto end;
  329. }
  330. pTG->gMonInfo.fInited=TRUE;
  331. fRet=TRUE;
  332. end:
  333. return fRet;
  334. }
  335. void MonDeInit(PThrdGlbl pTG)
  336. {
  337. if (!pTG->gMonInfo.fInited) { BG_CHK(FALSE); return; }
  338. // Free monbuf and mr array, if allocated.
  339. if (pTG->gMonInfo.fFreeOnExit)
  340. {
  341. MemFree(pTG->gMonInfo.lpbBuf);
  342. MemFree(pTG->gMonInfo.lpmrBuf);
  343. }
  344. _fmemset(&pTG->gMonInfo, 0, sizeof(pTG->gMonInfo));
  345. }
  346. BOOL MonPutComm(PThrdGlbl pTG, WORD wFlags, LPBYTE lpb, WORD wcb)
  347. // NOTE: special wFlags value (WORD)-1 indicates that
  348. // lpb is actually an entire MONFRAME_EVENT structure
  349. {
  350. DWORD cb0 = (DWORD)(pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf -
  351. pTG->gMonInfo.lpbNext);
  352. LPMONREC lpmrNext = pTG->gMonInfo.lpmrNext;
  353. if ((DWORD)wcb > pTG->gMonInfo.dwcbBuf) {BG_CHK(FALSE); return FALSE;}
  354. // +++Collapse into one bgchk after initial test.
  355. BG_CHK(pTG->gMonInfo.fInited);
  356. BG_CHK((pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf)>pTG->gMonInfo.lpbNext);
  357. BG_CHK(cb0<=pTG->gMonInfo.dwcbBuf);
  358. lpmrNext->dwTickCount=GetTickCount();
  359. lpmrNext->wFlags=wFlags;
  360. lpmrNext->wcb=wcb;
  361. // even on if !wcb we still keep the offset, for consistancy.
  362. lpmrNext->dwOffset=(DWORD)(pTG->gMonInfo.lpbNext-pTG->gMonInfo.lpbBuf);
  363. pTG->gMonInfo.dwNumBytes+=wcb;
  364. pTG->gMonInfo.dwNumPuts++;
  365. pTG->gMonInfo.lpmrNext++;
  366. if (pTG->gMonInfo.lpmrNext>=(pTG->gMonInfo.lpmrBuf+pTG->gMonInfo.dwcmrBuf))
  367. pTG->gMonInfo.lpmrNext = pTG->gMonInfo.lpmrBuf;
  368. if (wcb>cb0)
  369. {
  370. _fmemcpy(pTG->gMonInfo.lpbNext, lpb, cb0);
  371. pTG->gMonInfo.lpbNext=pTG->gMonInfo.lpbBuf;
  372. wcb-=(WORD)cb0;
  373. lpb+=cb0;
  374. }
  375. _fmemcpy(pTG->gMonInfo.lpbNext, lpb, wcb);
  376. pTG->gMonInfo.lpbNext+=wcb;
  377. if (pTG->gMonInfo.lpbNext >= (pTG->gMonInfo.lpbBuf+pTG->gMonInfo.dwcbBuf))
  378. pTG->gMonInfo.lpbNext = pTG->gMonInfo.lpbBuf;
  379. return TRUE;
  380. }
  381. BOOL MonPutEvent(PThrdGlbl pTG, WORD wFlags, WORD wID, WORD wSubID,
  382. DWORD dwData0, DWORD dwData1, LPSTR lpszTxtMsg)
  383. {
  384. // We actually call MonPutComm, with a "special" wFlag value of
  385. // (WORD) -1. MonDump looks for this special value and treates it
  386. // differently when writing out the record.
  387. char rgchBuf[sizeof(MONFRAME_EVENT)+MAX_TXTMSG_SIZE];
  388. LPMONFRAME_EVENT lpmfe=(LPMONFRAME_EVENT) rgchBuf;
  389. BOOL fRet=FALSE;
  390. lpmfe->wTxtMsgOff=
  391. lpmfe->wTotalSize=lpmfe->wHeaderSize=sizeof(MONFRAME_EVENT);
  392. lpmfe->wcbTxtMsg = (lpszTxtMsg) ? (WORD)lstrlen(lpszTxtMsg)+1:0;
  393. lpmfe->wTotalSize += lpmfe->wcbTxtMsg;
  394. if (lpmfe->wTotalSize>sizeof(rgchBuf)) goto end;
  395. lpmfe->wType = MFR_EVENT;
  396. lpmfe->wFlags = wFlags;
  397. lpmfe->dwTickCount = GetTickCount();
  398. lpmfe->wID=wID;
  399. lpmfe->wSubID=wSubID;
  400. lpmfe->dwInstanceID=pTG->gMonInfo.dwEventInstanceID++;
  401. lpmfe->dwData0=dwData0;
  402. lpmfe->dwData1=dwData1;
  403. GetLocalTime(&(lpmfe->st));
  404. if (lpmfe->wcbTxtMsg) _fmemcpy(((LPBYTE)lpmfe)+lpmfe->wTxtMsgOff,lpszTxtMsg, lpmfe->wcbTxtMsg);
  405. fRet = MonPutComm(pTG, (WORD)-1, (LPBYTE)lpmfe, lpmfe->wTotalSize);
  406. end:
  407. return fRet;
  408. }
  409. void MonDump(PThrdGlbl pTG)
  410. {
  411. HFILE hfile=HFILE_ERROR;
  412. LPMONREC lpmrFirst;
  413. DWORD dwcbBytesLeft;
  414. DWORD dwNumGoodMRs;
  415. if (!pTG->gMonInfo.fInited) {BG_CHK(FALSE); goto end;}
  416. GetLocalTime(&pTG->gMonInfo.stDump);
  417. hfile = iMonOpenAndWriteHeader(pTG);
  418. if (hfile==HFILE_ERROR) goto end;
  419. // Fixup offsets in MONREC structures to reflect the fact that
  420. // we're going to write starting from the oldest record onwards..
  421. //
  422. // This is a bit tricky because some of the MONREC structures may
  423. // not have associated data (the data could have been written over).
  424. // There may alternatively be data for which there are no MONREC structures
  425. // but that's OK.
  426. //
  427. // We start from the newest monrec structure and work our way backwards,
  428. // checking that the data is still valid and fixing up the offsets.
  429. if (pTG->gMonInfo.dwNumPuts<=pTG->gMonInfo.dwcmrBuf)
  430. lpmrFirst = pTG->gMonInfo.lpmrBuf;
  431. else
  432. lpmrFirst = pTG->gMonInfo.lpmrNext; // MONREC buffer rollover
  433. dwcbBytesLeft = pTG->gMonInfo.dwcbBuf; // we don't care if it's > than actually
  434. // in buffer.
  435. dwNumGoodMRs=0;
  436. if (pTG->gMonInfo.dwNumPuts && pTG->gMonInfo.dwNumBytes)
  437. {
  438. LPMONREC lpmr = pTG->gMonInfo.lpmrNext;
  439. // Starting with last monrec, work our way backwards...
  440. do
  441. {
  442. if (lpmr>pTG->gMonInfo.lpmrBuf)
  443. {lpmr--;}
  444. else
  445. {lpmr=pTG->gMonInfo.lpmrBuf+pTG->gMonInfo.dwcmrBuf-1;}
  446. if (lpmr->wcb <= dwcbBytesLeft)
  447. {
  448. dwcbBytesLeft-=lpmr->wcb;
  449. }
  450. else
  451. {
  452. // we've nuked one-or-more of the earlier structures because
  453. // their byte-data was overwritten.
  454. // So we reset lpmrFirst to the next MR structure.
  455. lpmrFirst=pTG->gMonInfo.lpmrBuf+
  456. ((lpmr+1-pTG->gMonInfo.lpmrBuf)%pTG->gMonInfo.dwcmrBuf);
  457. break;
  458. }
  459. dwNumGoodMRs++;
  460. } while (lpmr!=lpmrFirst);
  461. }
  462. iMonWriteFrames(pTG, hfile, (lpmrFirst-pTG->gMonInfo.lpmrBuf), dwNumGoodMRs);
  463. DosClose(hfile);
  464. pTG->gMonInfo.uRefCount++;
  465. pTG->gMonInfo.uRefCount&=0xf; // Limit number to 16
  466. end:
  467. return;
  468. }
  469. void imon_write(HFILE hfile, LPBYTE lpb, DWORD dwcb)
  470. {
  471. // Write out mon file, in chunks of 32K
  472. // -- because old mon code did that, perhaps a Win16 consideration.
  473. #define WRITESIZE (0x1L<<15)
  474. while(dwcb>=WRITESIZE)
  475. {
  476. DosWrite(hfile, lpb, WRITESIZE);
  477. lpb+=WRITESIZE;
  478. dwcb-=WRITESIZE;
  479. }
  480. if (dwcb)
  481. {
  482. DosWrite(hfile, lpb, dwcb);
  483. }
  484. }
  485. // Create a single file which contains the combined info in the
  486. // MONREC buffer and the byte buffer, in the form of MONFRAME
  487. // structures.
  488. // NOTE: special wFlags value (WORD)-1 indicates that
  489. // lpb is actually an entire MONFRAME_EVENT structure
  490. BOOL iMonWriteFrames(PThrdGlbl pTG, HFILE hfile, ULONG_PTR dwMROffset, DWORD dwcmr)
  491. {
  492. //BG_CHK((!dwMROffset && !dwcmr) || dwcmr<dwMROffset);
  493. // Simple version: don't bother caching
  494. {
  495. BYTE bBuf[sizeof(MONFRAME_COMM)];
  496. LPMONFRAME_COMM lpmfc = (LPMONFRAME_COMM) bBuf;
  497. LPMONREC lpmr = pTG->gMonInfo.lpmrBuf+dwMROffset;
  498. BG_CHK(dwMROffset<pTG->gMonInfo.dwcmrBuf);
  499. BG_CHK(dwcmr<=pTG->gMonInfo.dwcmrBuf);
  500. BG_CHK(dwcmr<=pTG->gMonInfo.dwNumPuts);
  501. while(dwcmr--)
  502. {
  503. DWORD dwcb0;
  504. BG_CHK((lpmr->wcb+sizeof(MONFRAME_COMM))<(1L<<(8*sizeof(WORD))));
  505. BG_CHK(lpmr->wcb<=pTG->gMonInfo.dwcbBuf);
  506. BG_CHK(lpmr->dwOffset<=pTG->gMonInfo.dwcbBuf);
  507. if (lpmr->wFlags != (WORD)-1) // See comment at head of function
  508. {
  509. lpmfc->wHeaderSize = sizeof(MONFRAME_COMM);
  510. lpmfc->wTotalSize = sizeof(MONFRAME_COMM)+lpmr->wcb;
  511. lpmfc->wType = MFR_COMMDATA;
  512. lpmfc->wFlags = lpmr->wFlags;
  513. lpmfc->dwTickCount = lpmr->dwTickCount;
  514. lpmfc->wcb = lpmr->wcb;
  515. imon_write(hfile, (LPBYTE)lpmfc, lpmfc->wHeaderSize);
  516. }
  517. dwcb0=pTG->gMonInfo.dwcbBuf-lpmr->dwOffset;
  518. if (lpmr->wcb<=dwcb0)
  519. {
  520. imon_write(hfile, pTG->gMonInfo.lpbBuf+lpmr->dwOffset, lpmr->wcb);
  521. }
  522. else
  523. {
  524. imon_write(hfile, pTG->gMonInfo.lpbBuf+lpmr->dwOffset, dwcb0);
  525. imon_write(hfile, pTG->gMonInfo.lpbBuf, lpmr->wcb-dwcb0);
  526. }
  527. if ( (lpmr+1-pTG->gMonInfo.lpmrBuf) < (long)pTG->gMonInfo.dwcmrBuf)
  528. lpmr++;
  529. else
  530. lpmr=pTG->gMonInfo.lpmrBuf;
  531. }
  532. }
  533. return TRUE;
  534. }
  535. HFILE iMonOpenAndWriteHeader(PThrdGlbl pTG)
  536. // Open file, if it's too big, rename old file and create file again.
  537. // If file empty, put signature
  538. // Put introductory timestamp text event.
  539. {
  540. UINT uHeaderSize=0;
  541. LPSTR lpszPathPrefix=pTG->gMonInfo.mo.rgchDir;
  542. char rgchPath[64];
  543. HFILE hfile = HFILE_ERROR;
  544. LONG l=0;
  545. if (!*lpszPathPrefix || (_fstrlen(lpszPathPrefix)+8) > sizeof (rgchPath))
  546. {
  547. lpszPathPrefix= "c:\\";
  548. }
  549. #define szMONFILESTUB "fax0"
  550. #define szRENAMED_MONFILESTUB "old"
  551. wsprintf(rgchPath, "%s%s", (LPSTR) lpszPathPrefix,
  552. (LPSTR) szMONFILESTUB "." szMON_EXT);
  553. // Try to open existing file.
  554. hfile = DosOpen(rgchPath, OF_READWRITE|OF_SHARE_DENY_WRITE);
  555. // Check if size is too big -- if so rename.
  556. if (hfile!=HFILE_ERROR)
  557. {
  558. l = DosSeek(hfile, 0, FILE_END);
  559. if (l==HFILE_ERROR) {DosClose(hfile); hfile=HFILE_ERROR; goto end;}
  560. if ((DWORD)l>pTG->gMonInfo.mo.dwMaxExistingSize)
  561. {
  562. char rgchRenamed[64];
  563. DosClose(hfile); hfile=HFILE_ERROR;
  564. wsprintf(rgchRenamed, "%s%s", (LPSTR) lpszPathPrefix,
  565. (LPSTR) szRENAMED_MONFILESTUB "." szMON_EXT);
  566. DeleteFile(rgchRenamed);
  567. MoveFile(rgchPath, rgchRenamed);
  568. }
  569. }
  570. if (hfile== HFILE_ERROR)
  571. {
  572. hfile = DosCreate(rgchPath, 0);
  573. if (hfile==HFILE_ERROR) goto end;
  574. l=0;
  575. }
  576. // Write header
  577. if (!l) {
  578. imon_write(hfile, szMONFRM_VER001 szMONFRM_DESC001,
  579. sizeof(szMONFRM_VER001 szMONFRM_DESC001));
  580. }
  581. // Create and write Text-frame with TIMESTAMP.
  582. {
  583. char rgchBuf[sizeof(MONFRAME_EVENT)+MAX_TXTMSG_SIZE];
  584. LPMONFRAME_EVENT lpmfe=(LPMONFRAME_EVENT) rgchBuf;
  585. UINT uTxtLen=0;
  586. lpmfe->wTxtMsgOff=
  587. lpmfe->wTotalSize=lpmfe->wHeaderSize=sizeof(MONFRAME_EVENT);
  588. lpmfe->wType = MFR_EVENT;
  589. lpmfe->wFlags = fEVENT_TRACELEVEL_0;
  590. lpmfe->dwTickCount = GetTickCount();
  591. lpmfe->wID= EVENT_ID_MON;
  592. lpmfe->wSubID= EVENT_SubID_MON_DUMP;
  593. lpmfe->dwInstanceID=pTG->gMonInfo.dwEventInstanceID++;
  594. lpmfe->dwData0=0;
  595. lpmfe->dwData1=0;
  596. GetLocalTime(&(lpmfe->st));
  597. uTxtLen = wsprintf(((LPBYTE)lpmfe)+lpmfe->wTxtMsgOff,
  598. "\tStarted: %02u/%02u/%04u %02u:%02u:%02u\r\n"
  599. "\t Puts: %lu/%lu\r\n"
  600. "\t Bytes: %lu/%lu\r\n",
  601. (unsigned) pTG->gMonInfo.stStart.wMonth&0xff,
  602. (unsigned) pTG->gMonInfo.stStart.wDay&0xff,
  603. (unsigned) pTG->gMonInfo.stStart.wYear&0xffff,
  604. (unsigned) pTG->gMonInfo.stStart.wHour&0xff,
  605. (unsigned) pTG->gMonInfo.stStart.wMinute&0xff,
  606. (unsigned) pTG->gMonInfo.stStart.wSecond&0xff,
  607. (unsigned) ((pTG->gMonInfo.dwcmrBuf>pTG->gMonInfo.dwNumPuts)
  608. ? pTG->gMonInfo.dwNumPuts: pTG->gMonInfo.dwcmrBuf),
  609. (unsigned) pTG->gMonInfo.dwNumPuts,
  610. (unsigned) ((pTG->gMonInfo.dwcbBuf>pTG->gMonInfo.dwNumBytes)
  611. ? pTG->gMonInfo.dwNumBytes: pTG->gMonInfo.dwcbBuf),
  612. (unsigned) pTG->gMonInfo.dwNumBytes);
  613. lpmfe->wcbTxtMsg = uTxtLen+1; // incuding zero.
  614. lpmfe->wTotalSize += lpmfe->wcbTxtMsg;
  615. BG_CHK(lpmfe->wTotalSize<=sizeof(rgchBuf));
  616. imon_write(hfile, (LPBYTE)lpmfe, lpmfe->wTotalSize);
  617. }
  618. end:
  619. return hfile;
  620. }
  621. #endif // MON3