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.

731 lines
30 KiB

  1. /**MOD+**********************************************************************/
  2. /* Module: atrcapi.c */
  3. /* */
  4. /* Purpose: External tracing functions */
  5. /* */
  6. /* Copyright(C) Microsoft Corporation 1996-7 */
  7. /* */
  8. /****************************************************************************/
  9. /** Changes:
  10. * $Log: Y:/logs/trc/atrcapi.c_v $
  11. *
  12. * Rev 1.12 22 Sep 1997 15:14:38 KH
  13. * SFR1293: Fix Zippy16 file write errors when zippy starts before Ducati
  14. *
  15. * Rev 1.11 05 Sep 1997 10:34:54 SJ
  16. * SFR1334: Zippy enhancements
  17. *
  18. * Rev 1.10 12 Aug 1997 09:45:28 MD
  19. * SFR1002: Remove kernel tracing code
  20. *
  21. * Rev 1.9 04 Aug 1997 15:03:26 KH
  22. * SFR1022: Cast file name length on sprintf call
  23. *
  24. * Rev 1.8 31 Jul 1997 19:39:30 SJ
  25. * SFR1041: Port zippy to Win16
  26. *
  27. * Rev 1.7 16 Jul 1997 14:00:48 KH
  28. * SFR1022: ALL functions are DCEXPORT
  29. *
  30. * Rev 1.6 11 Jul 1997 12:44:24 KH
  31. * SFR1022: Add DCEXPORT to TRC_GetBuffer
  32. *
  33. * Rev 1.4 09 Jul 1997 17:59:12 AK
  34. * SFR1016: Initial changes to support Unicode
  35. *
  36. * Rev 1.3 03 Jul 1997 13:27:24 AK
  37. * SFR0000: Initial development completed
  38. **/
  39. /**MOD-**********************************************************************/
  40. /****************************************************************************/
  41. /* */
  42. /* CONTENTS */
  43. /* */
  44. /* This file contains the DC-Groupware/NT tracing API. */
  45. /* */
  46. /****************************************************************************/
  47. /* */
  48. /* TRC_GetBuffer */
  49. /* TRC_TraceBuffer */
  50. /* TRC_GetConfig */
  51. /* TRC_SetConfig */
  52. /* TRC_TraceData */
  53. /* TRC_GetTraceLevel */
  54. /* TRC_ProfileTraceEnabled */
  55. /* TRC_ResetTraceFiles */
  56. /* */
  57. /****************************************************************************/
  58. /****************************************************************************/
  59. /* Standard includes. */
  60. /****************************************************************************/
  61. #include <adcg.h>
  62. /****************************************************************************/
  63. /* Define TRC_FILE and TRC_GROUP. */
  64. /****************************************************************************/
  65. #define TRC_FILE "atrcapi"
  66. #define TRC_GROUP TRC_GROUP_TRACE
  67. /****************************************************************************/
  68. /* Trace specific includes. */
  69. /****************************************************************************/
  70. #include <atrcapi.h>
  71. #include <atrcint.h>
  72. /****************************************************************************/
  73. /* */
  74. /* DATA */
  75. /* */
  76. /****************************************************************************/
  77. #define DC_INCLUDE_DATA
  78. #include <atrcdata.c>
  79. #undef DC_INCLUDE_DATA
  80. /****************************************************************************/
  81. /* */
  82. /* FUNCTIONS */
  83. /* */
  84. /****************************************************************************/
  85. /**PROC+*********************************************************************/
  86. /* TRC_GetBuffer(...) */
  87. /* */
  88. /* See atrcapi.h for description. */
  89. /**PROC-*********************************************************************/
  90. PDCTCHAR DCAPI DCEXPORT TRC_GetBuffer(DCVOID)
  91. {
  92. /************************************************************************/
  93. /* Get the mutex. Note that we do not need to check that we are */
  94. /* initialized in this function as this should have already been done. */
  95. /************************************************************************/
  96. TRCGrabMutex();
  97. //
  98. // Ensure null termination
  99. //
  100. trcpOutputBuffer[TRC_LINE_BUFFER_SIZE*sizeof(TCHAR) -1] = 0;
  101. /************************************************************************/
  102. /* Return a pointer to the trace buffer in the shared data memory */
  103. /* mapped file. */
  104. /************************************************************************/
  105. return(trcpOutputBuffer);
  106. } /* TRC_GetBuffer */
  107. /**PROC+*********************************************************************/
  108. /* TRC_TraceBuffer(...) */
  109. /* */
  110. /* See atrcapi.h for description. */
  111. /**PROC-*********************************************************************/
  112. DCVOID DCAPI DCEXPORT TRC_TraceBuffer(DCUINT traceLevel,
  113. DCUINT traceComponent,
  114. DCUINT lineNumber,
  115. PDCTCHAR funcName,
  116. PDCTCHAR fileName)
  117. {
  118. DCTCHAR fieldSeperator;
  119. DCTCHAR frmtString[TRC_FRMT_BUFFER_SIZE] = {0};
  120. DCTCHAR tempString[TRC_FRMT_BUFFER_SIZE] = {0};
  121. DCUINT32 processId;
  122. DCUINT32 threadId;
  123. DCUINT length;
  124. DC_TIME theTime;
  125. HRESULT hr;
  126. /************************************************************************/
  127. /* First of all we need to decide if we are going to trace this line. */
  128. /* */
  129. /* Note that the decision to trace a line based on its level is taken */
  130. /* in the TRACEX macro. */
  131. /************************************************************************/
  132. if (!TRCShouldTraceThis(traceComponent, traceLevel, fileName, lineNumber))
  133. {
  134. /********************************************************************/
  135. /* Don't bother tracing this line. */
  136. /********************************************************************/
  137. DC_QUIT;
  138. }
  139. /************************************************************************/
  140. /* We need to trace this line. First of all create the formatted */
  141. /* output text string. Determine the field seperator for the trace */
  142. /* line. Errors use a star (*), alerts a plus (+), asserts an */
  143. /* exclamation mark (!) while normal and debug trace lines both use a */
  144. /* space ( ). */
  145. /************************************************************************/
  146. switch(traceLevel)
  147. {
  148. case TRC_LEVEL_ASSERT:
  149. {
  150. fieldSeperator = '!';
  151. }
  152. break;
  153. case TRC_LEVEL_ERR:
  154. {
  155. fieldSeperator = '*';
  156. }
  157. break;
  158. case TRC_LEVEL_ALT:
  159. {
  160. fieldSeperator = '+';
  161. }
  162. break;
  163. case TRC_LEVEL_NRM:
  164. {
  165. fieldSeperator = ' ';
  166. }
  167. break;
  168. case TRC_LEVEL_DBG:
  169. {
  170. fieldSeperator = ' ';
  171. }
  172. break;
  173. case TRC_PROFILE_TRACE:
  174. {
  175. fieldSeperator = ' ';
  176. }
  177. break;
  178. default:
  179. {
  180. fieldSeperator = '?';
  181. }
  182. break;
  183. }
  184. /************************************************************************/
  185. /* Get the current process and thread Ids. */
  186. /************************************************************************/
  187. processId = TRCGetCurrentProcessId();
  188. threadId = TRCGetCurrentThreadId();
  189. /************************************************************************/
  190. /* Build the string to be printed out. First of all get the current */
  191. /* time. */
  192. /************************************************************************/
  193. TRCGetCurrentTime(&theTime);
  194. /************************************************************************/
  195. /* Now format the string. Note that the function name is of variable */
  196. /* length and given by <trcpConfig->funcNameLength>. */
  197. /************************************************************************/
  198. /************************************************************************/
  199. /* Go through each optional field and decide whether to add it to the */
  200. /* string or not. They are: */
  201. /* TRC_OPT_PROCESS_ID */
  202. /* TRC_OPT_THREAD_ID */
  203. /* TRC_OPT_TIME_STAMP */
  204. /* TRC_OPT_RELATIVE_TIME_STAMP */
  205. /************************************************************************/
  206. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_TIME_STAMP))
  207. {
  208. hr = StringCchPrintf(
  209. tempString,
  210. SIZE_TCHARS(tempString),
  211. TRC_TIME_FMT _T("%c"),
  212. theTime.hour,
  213. theTime.min,
  214. theTime.sec,
  215. theTime.hundredths,
  216. fieldSeperator
  217. );
  218. if (SUCCEEDED(hr)) {
  219. hr = StringCchCat(frmtString, SIZE_TCHARS(frmtString), tempString);
  220. if (FAILED(hr)) {
  221. DC_QUIT;
  222. }
  223. }
  224. else {
  225. DC_QUIT;
  226. }
  227. }
  228. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_PROCESS_ID))
  229. {
  230. hr = StringCchPrintf(tempString,
  231. SIZE_TCHARS(tempString),
  232. TRC_PROC_FMT,
  233. processId);
  234. if (SUCCEEDED(hr)) {
  235. hr = StringCchCat(frmtString, SIZE_TCHARS(frmtString), tempString);
  236. if (FAILED(hr)) {
  237. DC_QUIT;
  238. }
  239. }
  240. else {
  241. DC_QUIT;
  242. }
  243. }
  244. #ifdef OS_WIN32
  245. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_THREAD_ID))
  246. {
  247. /********************************************************************/
  248. /* Always put the colon before the thread ID so that, when only one */
  249. /* of the IDs is present, it is clear which it is. */
  250. /********************************************************************/
  251. hr = StringCchPrintf(tempString,
  252. SIZE_TCHARS(tempString),
  253. _T(":") TRC_THRD_FMT,
  254. threadId);
  255. if (SUCCEEDED(hr)) {
  256. hr = StringCchCat(frmtString, SIZE_TCHARS(frmtString), tempString);
  257. if (FAILED(hr)) {
  258. DC_QUIT;
  259. }
  260. }
  261. else {
  262. DC_QUIT;
  263. }
  264. }
  265. #endif
  266. #ifdef DC_OMIT
  267. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_RELATIVE_TIME_STAMP))
  268. {
  269. /********************************************************************/
  270. /* @@@ SJ - 090297 */
  271. /* The idea is to show some low-order portion of the timestamp */
  272. /* relative to the start time, in order to track timing issues. */
  273. /********************************************************************/
  274. }
  275. #endif
  276. hr = StringCchPrintf(tempString,
  277. SIZE_TCHARS(tempString),
  278. _T("%c") TRC_FUNC_FMT _T("%c") TRC_LINE_FMT _T("%c%s"),
  279. fieldSeperator,
  280. (DCINT)trcpConfig->funcNameLength,
  281. (DCINT)trcpConfig->funcNameLength,
  282. funcName,
  283. fieldSeperator,
  284. lineNumber,
  285. fieldSeperator,
  286. trcpOutputBuffer);
  287. if (SUCCEEDED(hr)) {
  288. hr = StringCchCat(frmtString, SIZE_TCHARS(frmtString), tempString);
  289. if (FAILED(hr)) {
  290. DC_QUIT;
  291. }
  292. }
  293. else {
  294. DC_QUIT;
  295. }
  296. /************************************************************************/
  297. /* Add CR:LF to the end and update the length of the string. */
  298. /************************************************************************/
  299. hr = StringCchCat(frmtString, SIZE_TCHARS(frmtString), TRC_CRLF);
  300. if (FAILED(hr)) {
  301. DC_QUIT;
  302. }
  303. length = DC_TSTRLEN(frmtString) * sizeof(DCTCHAR);
  304. /************************************************************************/
  305. /* Now that we have got the trace string, we need to write it out. */
  306. /************************************************************************/
  307. TRCOutput(frmtString, length, traceLevel);
  308. /************************************************************************/
  309. /* If this is an assert trace then we need to reformat the string for */
  310. /* use in the assert box. We must do this before we release the */
  311. /* mutex. */
  312. /************************************************************************/
  313. hr = StringCchPrintf(frmtString,
  314. SIZE_TCHARS(frmtString),
  315. TRC_ASSERT_TEXT,
  316. trcpOutputBuffer,
  317. funcName,
  318. fileName,
  319. lineNumber);
  320. if (FAILED(hr)) {
  321. DC_QUIT;
  322. }
  323. /************************************************************************/
  324. /* Decide if we need to do a stack trace. We must do this after */
  325. /* reformating the string as we use the shared trace buffer - if we */
  326. /* don't then we'll overwrite the original trace string! */
  327. /************************************************************************/
  328. if ((traceLevel >= TRC_LEVEL_ERR) && (traceLevel != TRC_PROFILE_TRACE))
  329. {
  330. TRCStackTrace(traceLevel);
  331. }
  332. DC_EXIT_POINT:
  333. /************************************************************************/
  334. /* Release the mutex. */
  335. /************************************************************************/
  336. TRCReleaseMutex();
  337. /************************************************************************/
  338. /* Now display the assert box - if an assert is already displayed then */
  339. /* <TRCDisplayAssertBox> will just return. */
  340. /************************************************************************/
  341. if (TRC_LEVEL_ASSERT == traceLevel)
  342. {
  343. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_BREAK_ON_ASSERT))
  344. {
  345. //
  346. // Break on assert so that we can actually get to see the assert
  347. // in situations like stress where the user may not be
  348. // watching for popups.
  349. //
  350. DebugBreak();
  351. }
  352. else
  353. {
  354. TRCDisplayAssertBox(frmtString);
  355. }
  356. }
  357. /************************************************************************/
  358. /* If this was an error level trace then we need to decide if we */
  359. /* should beep, and then if we should break into the debugger. */
  360. /************************************************************************/
  361. if (TRC_LEVEL_ERR == traceLevel)
  362. {
  363. /********************************************************************/
  364. /* Test if we should beep. */
  365. /********************************************************************/
  366. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_BEEP_ON_ERROR))
  367. {
  368. TRCBeep();
  369. }
  370. /********************************************************************/
  371. /* Test if we should break into the debugger. Note that we have */
  372. /* released the mutex, so other processes can continue to trace. */
  373. /********************************************************************/
  374. if (TEST_FLAG(trcpConfig->flags, TRC_OPT_BREAK_ON_ERROR))
  375. {
  376. TRCDebugBreak();
  377. }
  378. }
  379. } /* TRC_TraceBuffer */
  380. /**PROC+*********************************************************************/
  381. /* TRC_GetConfig(...) */
  382. /* */
  383. /* See atrcapi.h for description. */
  384. /**PROC-*********************************************************************/
  385. DCBOOL DCAPI DCEXPORT TRC_GetConfig(PTRC_CONFIG pTraceConfig,
  386. DCUINT length)
  387. {
  388. DCBOOL rc = TRUE;
  389. /************************************************************************/
  390. /* Check to ensure that the current state is valid. If it is not then */
  391. /* just quit. */
  392. /************************************************************************/
  393. if ( trcpConfig == NULL )
  394. {
  395. TRCOpenSharedData();
  396. }
  397. else
  398. {
  399. TRCReadSharedDataConfig();
  400. }
  401. /************************************************************************/
  402. /* Copy information from fixed structure to callers structure. */
  403. /************************************************************************/
  404. DC_MEMCPY(pTraceConfig,
  405. trcpConfig,
  406. DC_MIN(length, sizeof(TRC_CONFIG)));
  407. DC_EXIT_POINT:
  408. return(rc);
  409. } /* TRC_GetConfig */
  410. /**PROC+*********************************************************************/
  411. /* TRC_SetConfig(...) */
  412. /* */
  413. /* See atrcapi.h for description. */
  414. /**PROC-*********************************************************************/
  415. DCBOOL DCAPI DCEXPORT TRC_SetConfig(PTRC_CONFIG pTraceConfig,
  416. DCUINT length)
  417. {
  418. DCBOOL rc = TRUE;
  419. DCUINT i;
  420. DCUINT32 maxFileSize;
  421. DCTCHAR fileNames[TRC_NUM_FILES][TRC_FILE_NAME_SIZE];
  422. HRESULT hr;
  423. /************************************************************************/
  424. /* Check to ensure that the current state is valid. If it is not then */
  425. /* just quit. */
  426. /************************************************************************/
  427. if ( trcpConfig == NULL )
  428. {
  429. TRCOpenSharedData();
  430. }
  431. else
  432. {
  433. TRCReadSharedDataConfig();
  434. }
  435. /************************************************************************/
  436. /* We do not support dynamic modification of the maximum trace file */
  437. /* size or of the trace file names. Therefore we store these before a */
  438. /* change and overwrite the new values to ensure that they do not */
  439. /* change. */
  440. /************************************************************************/
  441. maxFileSize = trcpConfig->maxFileSize;
  442. for (i = 0; i < TRC_NUM_FILES; i++)
  443. {
  444. StringCchCopy(fileNames[i], TRC_FILE_NAME_SIZE,
  445. trcpConfig->fileNames[i]);
  446. }
  447. /************************************************************************/
  448. /* Copy information from fixed structure to callers structure. */
  449. /************************************************************************/
  450. DC_MEMCPY(trcpConfig,
  451. pTraceConfig,
  452. DC_MIN(length, sizeof(TRC_CONFIG)));
  453. /************************************************************************/
  454. /* Now restore the maximum trace file size and the trace file names. */
  455. /************************************************************************/
  456. trcpConfig->maxFileSize = maxFileSize;
  457. for (i = 0; i < TRC_NUM_FILES; i++)
  458. {
  459. StringCchCopy(trcpConfig->fileNames[i],
  460. SIZE_TCHARS(trcpConfig->fileNames[i]),
  461. fileNames[i]);
  462. }
  463. /************************************************************************/
  464. /* Split the prefix list. */
  465. /************************************************************************/
  466. TRCSplitPrefixes();
  467. /************************************************************************/
  468. /* Store the new configuration data. */
  469. /************************************************************************/
  470. TRCWriteSharedDataConfig();
  471. DC_EXIT_POINT:
  472. return(rc);
  473. } /* TRC_SetConfig */
  474. /**PROC+*********************************************************************/
  475. /* TRC_TraceData(...) */
  476. /* */
  477. /* See atrcapi.h for description. */
  478. /**PROC-*********************************************************************/
  479. DCVOID DCAPI DCEXPORT TRC_TraceData(DCUINT traceLevel,
  480. DCUINT traceComponent,
  481. DCUINT lineNumber,
  482. PDCTCHAR funcName,
  483. PDCTCHAR fileName,
  484. PDCUINT8 buffer,
  485. DCUINT bufLength)
  486. {
  487. DCUINT i;
  488. /************************************************************************/
  489. /* If the trace checks fail then exit immediately. */
  490. /************************************************************************/
  491. if (!TRCShouldTraceThis(traceComponent, traceLevel, fileName, lineNumber))
  492. {
  493. /********************************************************************/
  494. /* Don't bother tracing this data. */
  495. /********************************************************************/
  496. DC_QUIT;
  497. }
  498. /************************************************************************/
  499. /* Truncate the length, if necessary. */
  500. /************************************************************************/
  501. if (bufLength > trcpConfig->dataTruncSize)
  502. {
  503. bufLength = (DCUINT)trcpConfig->dataTruncSize;
  504. }
  505. /************************************************************************/
  506. /* TRC_TraceBuffer will decrement the mutex usage count for us - so we */
  507. /* need to pre-increment it before calling TRC_BufferTrace. This */
  508. /* ensures that we still have the mutex when we come to trace the data */
  509. /* out. */
  510. /************************************************************************/
  511. TRCGrabMutex();
  512. /************************************************************************/
  513. /* Now trace out the description string. */
  514. /************************************************************************/
  515. TRC_TraceBuffer(traceLevel,
  516. traceComponent,
  517. lineNumber,
  518. funcName,
  519. fileName);
  520. /************************************************************************/
  521. /* Now trace the data portion. */
  522. /************************************************************************/
  523. for (i = 0; (i + 15) < bufLength; i += 16)
  524. {
  525. TRCDumpLine(buffer, 16, i, traceLevel);
  526. buffer += 16;
  527. }
  528. /************************************************************************/
  529. /* Check to see if we have a partial line to output. */
  530. /************************************************************************/
  531. if ((bufLength%16) > 0)
  532. {
  533. /********************************************************************/
  534. /* Do partial line last. */
  535. /********************************************************************/
  536. TRCDumpLine(buffer, (bufLength%16), i, (DCUINT)traceLevel);
  537. }
  538. DC_EXIT_POINT:
  539. /************************************************************************/
  540. /* Finally free the mutex. */
  541. /************************************************************************/
  542. TRCReleaseMutex();
  543. return;
  544. } /* TRC_TraceData */
  545. /**PROC+*********************************************************************/
  546. /* TRC_GetTraceLevel(...) */
  547. /* */
  548. /* See atrcapi.h for description. */
  549. /**PROC-*********************************************************************/
  550. DCUINT DCAPI DCEXPORT TRC_GetTraceLevel(DCVOID)
  551. {
  552. DCUINT32 rc = TRC_LEVEL_DIS;
  553. /************************************************************************/
  554. /* Check to ensure that the current state is valid. If it is not then */
  555. /* just quit. */
  556. /************************************************************************/
  557. if (!TRCCheckState())
  558. {
  559. DC_QUIT;
  560. }
  561. /************************************************************************/
  562. /* Get the current trace level. */
  563. /************************************************************************/
  564. rc = trcpConfig->traceLevel;
  565. DC_EXIT_POINT:
  566. return((DCUINT)rc);
  567. } /* TRC_GetTraceLevel */
  568. /**PROC+*********************************************************************/
  569. /* TRC_ProfileTraceEnabled */
  570. /* */
  571. /* See atrcapi.h for description. */
  572. /**PROC-*********************************************************************/
  573. DCBOOL DCAPI DCEXPORT TRC_ProfileTraceEnabled(DCVOID)
  574. {
  575. DCBOOL prfTrace = FALSE;
  576. /************************************************************************/
  577. /* Check to ensure that the current state is valid. If it is not then */
  578. /* just quit. */
  579. /************************************************************************/
  580. if (!TRCCheckState())
  581. {
  582. DC_QUIT;
  583. }
  584. /************************************************************************/
  585. /* Get the setting of the flag and return TRUE if function profile */
  586. /* tracing is supported. */
  587. /************************************************************************/
  588. prfTrace = TEST_FLAG(trcpConfig->flags, TRC_OPT_PROFILE_TRACING);
  589. DC_EXIT_POINT:
  590. return(prfTrace);
  591. } /* TRC_ProfileTraceEnabled */
  592. /**PROC+*********************************************************************/
  593. /* TRC_ResetTraceFiles */
  594. /* */
  595. /* See atrcapi.h for description. */
  596. /**PROC-*********************************************************************/
  597. DCBOOL DCAPI DCEXPORT TRC_ResetTraceFiles(DCVOID)
  598. {
  599. DCBOOL rc = TRUE;
  600. /************************************************************************/
  601. /* Check to ensure that the current state is valid. If it is not then */
  602. /* just quit. */
  603. /************************************************************************/
  604. if (!TRCCheckState())
  605. {
  606. rc = FALSE;
  607. DC_QUIT;
  608. }
  609. /************************************************************************/
  610. /* Grab the mutex. */
  611. /************************************************************************/
  612. TRCGrabMutex();
  613. /************************************************************************/
  614. /* Call the OS specific function to reset the trace files. */
  615. /************************************************************************/
  616. TRCResetTraceFiles();
  617. /************************************************************************/
  618. /* Release the mutex. */
  619. /************************************************************************/
  620. TRCReleaseMutex();
  621. DC_EXIT_POINT:
  622. return(rc);
  623. } /* TRC_ResetTraceFiles */
  624. //
  625. // Sprintf that will take care of truncating to the trace buffer size
  626. //
  627. #ifndef TRC_SAFER_SPRINTF
  628. #define TRC_SAFER_SPRINTF
  629. VOID TRCSaferSprintf(PDCTCHAR outBuf, UINT cchLen, const PDCTCHAR format,...)
  630. {
  631. HRESULT hr;
  632. va_list vaArgs;
  633. va_start(vaArgs, format);
  634. hr = StringCchVPrintf(outBuf,
  635. cchLen,
  636. format,
  637. vaArgs);
  638. va_end(vaArgs);
  639. }
  640. #endif