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.

1065 lines
26 KiB

  1. /*******************************************************************************
  2. *
  3. * TRACE.C
  4. * This module implements the trace functions
  5. *
  6. * Copyright 1998, Microsoft.
  7. *
  8. *
  9. ******************************************************************************/
  10. /*
  11. * Includes
  12. */
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. #include <ctxdd.h>
  16. /*=============================================================================
  17. == External Functions Defined
  18. =============================================================================*/
  19. NTSTATUS IcaStartStopTrace( PICA_TRACE_INFO, PICA_TRACE );
  20. VOID _cdecl IcaSystemTrace( ULONG, ULONG, CHAR *, ... );
  21. VOID IcaSystemTraceBuffer( ULONG, ULONG, PVOID, ULONG );
  22. VOID _cdecl IcaStackTrace( PSDCONTEXT, ULONG, ULONG, CHAR *, ... );
  23. VOID IcaStackTraceBuffer( PSDCONTEXT, ULONG, ULONG, PVOID, ULONG );
  24. VOID IcaTraceFormat( PICA_TRACE_INFO, ULONG, ULONG, CHAR * );
  25. VOID _cdecl _IcaTrace( PICA_CONNECTION, ULONG, ULONG, CHAR *, ... );
  26. VOID _cdecl _IcaStackTrace( PICA_STACK, ULONG, ULONG, CHAR *, ... );
  27. VOID _IcaStackTraceBuffer( PICA_STACK, ULONG, ULONG, PVOID, ULONG );
  28. VOID _cdecl _IcaChannelTrace( PICA_CHANNEL, ULONG, ULONG, CHAR *, ... );
  29. /*=============================================================================
  30. == Internal functions
  31. =============================================================================*/
  32. NTSTATUS _IcaOpenTraceFile( PICA_TRACE_INFO, PWCHAR );
  33. VOID _IcaCloseTraceFile( PICA_TRACE_INFO );
  34. VOID _IcaTraceWrite( PICA_TRACE_INFO, PVOID );
  35. VOID _IcaFlushDeferredTrace( PICA_TRACE_INFO );
  36. int _FormatTime( CHAR *, ULONG );
  37. int _FormatThreadId( CHAR *, ULONG );
  38. VOID _WriteHexData( PICA_TRACE_INFO, PVOID, ULONG );
  39. /*=============================================================================
  40. == Global variables
  41. =============================================================================*/
  42. /*
  43. * Trace info
  44. */
  45. ICA_TRACE_INFO G_TraceInfo = { 0, 0, FALSE, FALSE, NULL, NULL, NULL };
  46. /*******************************************************************************
  47. *
  48. * IcaStartStopTrace
  49. *
  50. * Start/stop tracing
  51. *
  52. * ENTRY:
  53. * pTraceInfo (input)
  54. * pointer to ICA_TRACE_INFO struct
  55. * pTrace (input)
  56. * pointer to ICA_TRACE (IOCTL) trace settings
  57. *
  58. * EXIT:
  59. * STATUS_SUCCESS - no error
  60. *
  61. ******************************************************************************/
  62. NTSTATUS
  63. IcaStartStopTrace(
  64. IN PICA_TRACE_INFO pTraceInfo,
  65. IN PICA_TRACE pTrace
  66. )
  67. {
  68. NTSTATUS Status;
  69. /*
  70. * If a trace file was specified,
  71. * then open it and save a pointer to the file object.
  72. */
  73. if ( pTrace->TraceFile[0] ) {
  74. /*
  75. * Force a null termination for file name.
  76. */
  77. pTrace->TraceFile[255] = (WCHAR)0;
  78. Status = _IcaOpenTraceFile( pTraceInfo, pTrace->TraceFile );
  79. if ( !NT_SUCCESS( Status ) )
  80. return( Status );
  81. /*
  82. * If no trace file specified, then close any existing trace file
  83. */
  84. } else if ( pTraceInfo->pTraceFileName ) {
  85. _IcaCloseTraceFile( pTraceInfo );
  86. }
  87. /*
  88. * Set trace flags
  89. */
  90. pTraceInfo->fTraceDebugger = pTrace->fDebugger;
  91. pTraceInfo->fTraceTimestamp = pTrace->fTimestamp;
  92. pTraceInfo->TraceClass = pTrace->TraceClass;
  93. pTraceInfo->TraceEnable = pTrace->TraceEnable;
  94. return( STATUS_SUCCESS );
  95. }
  96. /*******************************************************************************
  97. *
  98. * IcaSystemTrace
  99. *
  100. * This routine conditional writes a trace record to the system trace file
  101. *
  102. * ENTRY:
  103. * TraceClass (input)
  104. * trace class bit mask
  105. * TraceEnable (input)
  106. * trace type bit mask
  107. * Format (input)
  108. * format string
  109. * ... (input)
  110. * enough arguments to satisfy format string
  111. *
  112. * EXIT:
  113. * nothing
  114. *
  115. ******************************************************************************/
  116. VOID _cdecl
  117. IcaSystemTrace( IN ULONG TraceClass,
  118. IN ULONG TraceEnable,
  119. IN CHAR * Format,
  120. IN ... )
  121. {
  122. va_list arg_marker;
  123. char Buffer[256];
  124. va_start( arg_marker, Format );
  125. /*
  126. * Check if this trace record should be output
  127. */
  128. if ( !(TraceClass & G_TraceInfo.TraceClass) || !(TraceEnable & G_TraceInfo.TraceEnable) )
  129. return;
  130. /*
  131. * Format trace data
  132. */
  133. _vsnprintf( Buffer, sizeof(Buffer), Format, arg_marker );
  134. /*
  135. * Write trace data
  136. */
  137. IcaTraceFormat( &G_TraceInfo, TraceClass, TraceEnable, Buffer );
  138. }
  139. /*******************************************************************************
  140. *
  141. * IcaSystemTraceBuffer
  142. *
  143. * This routine conditional writes a data buffer to the system trace file
  144. *
  145. * ENTRY:
  146. * TraceClass (input)
  147. * trace class bit mask
  148. * TraceEnable (input)
  149. * trace type bit mask
  150. * pBuffer (input)
  151. * pointer to data buffer
  152. * ByteCount (input)
  153. * length of buffer
  154. *
  155. * EXIT:
  156. * nothing
  157. *
  158. ******************************************************************************/
  159. VOID
  160. IcaSystemTraceBuffer( IN ULONG TraceClass,
  161. IN ULONG TraceEnable,
  162. IN PVOID pBuffer,
  163. IN ULONG ByteCount )
  164. {
  165. /*
  166. * Check if this trace record should be output
  167. */
  168. if ( !(TraceClass & G_TraceInfo.TraceClass) ||
  169. !(TraceEnable & G_TraceInfo.TraceEnable) )
  170. return;
  171. /*
  172. * Write trace data
  173. */
  174. _WriteHexData( &G_TraceInfo, pBuffer, ByteCount );
  175. }
  176. /*******************************************************************************
  177. *
  178. * IcaStackTrace
  179. *
  180. * This routine conditional writes a trace record depending on the trace mask
  181. *
  182. * ENTRY:
  183. * pContext (input)
  184. * pointer to stack driver context
  185. * TraceClass (input)
  186. * trace class bit mask
  187. * TraceEnable (input)
  188. * trace type bit mask
  189. * Format (input)
  190. * format string
  191. * ... (input)
  192. * enough arguments to satisfy format string
  193. *
  194. * EXIT:
  195. * nothing
  196. *
  197. ******************************************************************************/
  198. VOID _cdecl
  199. IcaStackTrace( IN PSDCONTEXT pContext,
  200. IN ULONG TraceClass,
  201. IN ULONG TraceEnable,
  202. IN CHAR * Format,
  203. IN ... )
  204. {
  205. va_list arg_marker;
  206. char Buffer[256];
  207. PICA_STACK pStack;
  208. PICA_CONNECTION pConnect;
  209. PICA_TRACE_INFO pTraceInfo;
  210. va_start( arg_marker, Format );
  211. /*
  212. * Use SD passed context to get the STACK object pointer.
  213. */
  214. pStack = (CONTAINING_RECORD( pContext, SDLINK, SdContext ))->pStack;
  215. pConnect = IcaGetConnectionForStack( pStack );
  216. /*
  217. * Check if this trace record should be output
  218. */
  219. pTraceInfo = &pConnect->TraceInfo;
  220. if ( !(TraceClass & pTraceInfo->TraceClass) ||
  221. !(TraceEnable & pTraceInfo->TraceEnable) )
  222. return;
  223. /*
  224. * Format trace data
  225. */
  226. _vsnprintf( Buffer, sizeof(Buffer), Format, arg_marker );
  227. /*
  228. * Write trace data
  229. */
  230. IcaTraceFormat( pTraceInfo, TraceClass, TraceEnable, Buffer );
  231. }
  232. /*******************************************************************************
  233. *
  234. * IcaStackTraceBuffer
  235. *
  236. * This routine conditional writes a data buffer to the trace file
  237. *
  238. * ENTRY:
  239. * pContext (input)
  240. * pointer to stack driver context
  241. * TraceClass (input)
  242. * trace class bit mask
  243. * TraceEnable (input)
  244. * trace type bit mask
  245. * pBuffer (input)
  246. * pointer to data buffer
  247. * ByteCount (input)
  248. * length of buffer
  249. *
  250. * EXIT:
  251. * nothing
  252. *
  253. ******************************************************************************/
  254. VOID
  255. IcaStackTraceBuffer( IN PSDCONTEXT pContext,
  256. IN ULONG TraceClass,
  257. IN ULONG TraceEnable,
  258. IN PVOID pBuffer,
  259. IN ULONG ByteCount )
  260. {
  261. PICA_TRACE_INFO pTraceInfo;
  262. PICA_STACK pStack;
  263. PICA_CONNECTION pConnect;
  264. /*
  265. * Use SD passed context to get the STACK object pointer.
  266. */
  267. pStack = (CONTAINING_RECORD( pContext, SDLINK, SdContext ))->pStack;
  268. pConnect = IcaGetConnectionForStack( pStack );
  269. /*
  270. * Check if this trace record should be output
  271. */
  272. pTraceInfo = &pConnect->TraceInfo;
  273. if ( !(TraceClass & pTraceInfo->TraceClass) ||
  274. !(TraceEnable & pTraceInfo->TraceEnable) )
  275. return;
  276. /*
  277. * Write trace data
  278. */
  279. _WriteHexData( pTraceInfo, pBuffer, ByteCount );
  280. }
  281. /*******************************************************************************
  282. *
  283. * IcaTraceFormat
  284. *
  285. * This routine conditional writes trace data depending on the trace mask
  286. *
  287. * ENTRY:
  288. * pTraceInfo (input)
  289. * pointer to ICA_TRACE_INFO struct
  290. * TraceClass (input)
  291. * trace class bit mask
  292. * TraceEnable (input)
  293. * trace type bit mask
  294. * pData (input)
  295. * pointer to null terminated trace data
  296. *
  297. * EXIT:
  298. * nothing
  299. *
  300. ******************************************************************************/
  301. VOID
  302. IcaTraceFormat( IN PICA_TRACE_INFO pTraceInfo,
  303. IN ULONG TraceClass,
  304. IN ULONG TraceEnable,
  305. IN CHAR * pData )
  306. {
  307. char Buffer[256];
  308. char * pBuf;
  309. int len = 0;
  310. int i;
  311. /*
  312. * Check if this trace record should be output
  313. */
  314. if ( !(TraceClass & pTraceInfo->TraceClass) || !(TraceEnable & pTraceInfo->TraceEnable) )
  315. return;
  316. pBuf = Buffer;
  317. /*
  318. * Append time stamp
  319. */
  320. if ( pTraceInfo->fTraceTimestamp ) {
  321. len = _FormatTime( pBuf, sizeof(Buffer) );
  322. pBuf += len;
  323. }
  324. /*
  325. * Append thread id
  326. */
  327. i = _FormatThreadId( pBuf, sizeof(Buffer) - len );
  328. len += i;
  329. pBuf += i;
  330. /*
  331. * Append trace data
  332. */
  333. _snprintf( pBuf, sizeof(Buffer) - len, pData );
  334. /*
  335. * Write trace data
  336. */
  337. _IcaTraceWrite( pTraceInfo, Buffer );
  338. }
  339. /*******************************************************************************
  340. *
  341. * _IcaTrace
  342. *
  343. * Write a trace record to the winstation trace file
  344. *
  345. * ENTRY:
  346. * pConnect (input)
  347. * pointer to connection structure
  348. * TraceClass (input)
  349. * trace class bit mask
  350. * TraceEnable (input)
  351. * trace type bit mask
  352. * Format (input)
  353. * format string
  354. * ... (input)
  355. * enough arguments to satisfy format string
  356. *
  357. * EXIT:
  358. * nothing
  359. *
  360. ******************************************************************************/
  361. VOID _cdecl
  362. _IcaTrace( IN PICA_CONNECTION pConnect,
  363. IN ULONG TraceClass,
  364. IN ULONG TraceEnable,
  365. IN CHAR * Format,
  366. IN ... )
  367. {
  368. va_list arg_marker;
  369. char Buffer[256];
  370. PICA_TRACE_INFO pTraceInfo;
  371. ASSERT( pConnect->Header.Type == IcaType_Connection );
  372. va_start( arg_marker, Format );
  373. pTraceInfo = &pConnect->TraceInfo;
  374. /*
  375. * Check if this trace record should be output
  376. */
  377. if ( !(TraceClass & pTraceInfo->TraceClass) || !(TraceEnable & pTraceInfo->TraceEnable) )
  378. return;
  379. /*
  380. * Format trace data
  381. */
  382. _vsnprintf( Buffer, sizeof(Buffer), Format, arg_marker );
  383. /*
  384. * Write trace data
  385. */
  386. IcaTraceFormat( pTraceInfo, TraceClass, TraceEnable, Buffer );
  387. }
  388. /*******************************************************************************
  389. *
  390. * _IcaStackTrace
  391. *
  392. * Write a trace record to the winstation trace file
  393. *
  394. * ENTRY:
  395. * pStack (input)
  396. * pointer to stack structure
  397. * TraceClass (input)
  398. * trace class bit mask
  399. * TraceEnable (input)
  400. * trace type bit mask
  401. * Format (input)
  402. * format string
  403. * ... (input)
  404. * enough arguments to satisfy format string
  405. *
  406. * EXIT:
  407. * nothing
  408. *
  409. ******************************************************************************/
  410. VOID _cdecl
  411. _IcaStackTrace( IN PICA_STACK pStack,
  412. IN ULONG TraceClass,
  413. IN ULONG TraceEnable,
  414. IN CHAR * Format,
  415. IN ... )
  416. {
  417. va_list arg_marker;
  418. char Buffer[256];
  419. PICA_CONNECTION pConnect;
  420. PICA_TRACE_INFO pTraceInfo;
  421. ASSERT( pStack->Header.Type == IcaType_Stack );
  422. va_start( arg_marker, Format );
  423. pConnect = IcaGetConnectionForStack( pStack );
  424. /*
  425. * Check if this trace record should be output
  426. */
  427. pTraceInfo = &pConnect->TraceInfo;
  428. if ( !(TraceClass & pTraceInfo->TraceClass) ||
  429. !(TraceEnable & pTraceInfo->TraceEnable) )
  430. return;
  431. /*
  432. * Format trace data
  433. */
  434. _vsnprintf( Buffer, sizeof(Buffer), Format, arg_marker );
  435. /*
  436. * Write trace data
  437. */
  438. IcaTraceFormat( pTraceInfo, TraceClass, TraceEnable, Buffer );
  439. }
  440. /*******************************************************************************
  441. *
  442. * _IcaStackTraceBuffer
  443. *
  444. * This routine conditional writes a data buffer to the trace file
  445. *
  446. * ENTRY:
  447. * pStack (input)
  448. * pointer to stack structure
  449. * TraceClass (input)
  450. * trace class bit mask
  451. * TraceEnable (input)
  452. * trace type bit mask
  453. * pBuffer (input)
  454. * pointer to data buffer
  455. * ByteCount (input)
  456. * length of buffer
  457. *
  458. * EXIT:
  459. * nothing
  460. *
  461. ******************************************************************************/
  462. VOID
  463. _IcaStackTraceBuffer( IN PICA_STACK pStack,
  464. IN ULONG TraceClass,
  465. IN ULONG TraceEnable,
  466. IN PVOID pBuffer,
  467. IN ULONG ByteCount )
  468. {
  469. PICA_CONNECTION pConnect;
  470. PICA_TRACE_INFO pTraceInfo;
  471. ASSERT( pStack->Header.Type == IcaType_Stack );
  472. pConnect = IcaGetConnectionForStack( pStack );
  473. /*
  474. * Check if this trace record should be output
  475. */
  476. pTraceInfo = &pConnect->TraceInfo;
  477. if ( !(TraceClass & pTraceInfo->TraceClass) ||
  478. !(TraceEnable & pTraceInfo->TraceEnable) )
  479. return;
  480. /*
  481. * Write trace data
  482. */
  483. _WriteHexData( pTraceInfo, pBuffer, ByteCount );
  484. }
  485. /*******************************************************************************
  486. *
  487. * _IcaChannelTrace
  488. *
  489. * Write a trace record to the winstation trace file
  490. *
  491. * ENTRY:
  492. * pChannel (input)
  493. * pointer to Channel structure
  494. * TraceClass (input)
  495. * trace class bit mask
  496. * TraceEnable (input)
  497. * trace type bit mask
  498. * Format (input)
  499. * format string
  500. * ... (input)
  501. * enough arguments to satisfy format string
  502. *
  503. * EXIT:
  504. * nothing
  505. *
  506. ******************************************************************************/
  507. VOID _cdecl
  508. _IcaChannelTrace( IN PICA_CHANNEL pChannel,
  509. IN ULONG TraceClass,
  510. IN ULONG TraceEnable,
  511. IN CHAR * Format,
  512. IN ... )
  513. {
  514. va_list arg_marker;
  515. char Buffer[256];
  516. PICA_TRACE_INFO pTraceInfo;
  517. ASSERT( pChannel->Header.Type == IcaType_Channel );
  518. va_start( arg_marker, Format );
  519. pTraceInfo = &pChannel->pConnect->TraceInfo;
  520. /*
  521. * Check if this trace record should be output
  522. */
  523. if ( !(TraceClass & pTraceInfo->TraceClass) || !(TraceEnable & pTraceInfo->TraceEnable) )
  524. return;
  525. /*
  526. * Format trace data
  527. */
  528. _vsnprintf( Buffer, sizeof(Buffer), Format, arg_marker );
  529. /*
  530. * Write trace data
  531. */
  532. IcaTraceFormat( pTraceInfo, TraceClass, TraceEnable, Buffer );
  533. }
  534. /*******************************************************************************
  535. *
  536. * _IcaOpenTraceFile
  537. *
  538. * Open a trace file
  539. *
  540. * ENTRY:
  541. * pTraceInfo (input)
  542. * pointer to ICA_TRACE_INFO struct
  543. * pTraceFile (input)
  544. * pointer to trace file name
  545. *
  546. * EXIT:
  547. * STATUS_SUCCESS - no error
  548. *
  549. ******************************************************************************/
  550. #define NAMEPREFIX L"\\DosDevices\\"
  551. NTSTATUS
  552. _IcaOpenTraceFile(
  553. IN PICA_TRACE_INFO pTraceInfo,
  554. IN PWCHAR pTraceFile
  555. )
  556. {
  557. UNICODE_STRING TraceString;
  558. OBJECT_ATTRIBUTES ObjectAttributes;
  559. IO_STATUS_BLOCK iosb;
  560. HANDLE TraceFileHandle;
  561. PFILE_OBJECT pTraceFileObject;
  562. ULONG PrefixLength;
  563. ULONG TraceFileLength;
  564. NTSTATUS Status;
  565. PrefixLength = wcslen( NAMEPREFIX ) * sizeof(WCHAR);
  566. TraceFileLength = wcslen( pTraceFile ) * sizeof(WCHAR);
  567. TraceString.Length = (USHORT) (PrefixLength + TraceFileLength);
  568. TraceString.MaximumLength = TraceString.Length + sizeof(UNICODE_NULL);
  569. TraceString.Buffer = ICA_ALLOCATE_POOL( NonPagedPool, TraceString.MaximumLength );
  570. if (TraceString.Buffer != NULL) {
  571. RtlCopyMemory( TraceString.Buffer, NAMEPREFIX, PrefixLength );
  572. RtlCopyMemory( (char *)TraceString.Buffer + PrefixLength, pTraceFile, TraceFileLength );
  573. TraceString.Buffer[(PrefixLength + TraceFileLength) / sizeof(WCHAR)] = UNICODE_NULL;
  574. }
  575. else {
  576. return STATUS_NO_MEMORY;
  577. }
  578. /*
  579. * If we already have a trace file and the name is the same
  580. * as a previous call, then there's nothing to be done.
  581. */
  582. if ( pTraceInfo->pTraceFileName != NULL &&
  583. !_wcsicmp( TraceString.Buffer, pTraceInfo->pTraceFileName ) ) {
  584. ICA_FREE_POOL( TraceString.Buffer );
  585. return( STATUS_SUCCESS );
  586. }
  587. /*
  588. * Close the existing trace file if there is one
  589. */
  590. if ( pTraceInfo->pTraceFileName ) {
  591. _IcaCloseTraceFile( pTraceInfo );
  592. }
  593. InitializeObjectAttributes( &ObjectAttributes, &TraceString,
  594. OBJ_CASE_INSENSITIVE, NULL, NULL );
  595. Status = ZwCreateFile(
  596. &TraceFileHandle,
  597. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  598. &ObjectAttributes,
  599. &iosb, // returned status information.
  600. 0, // block size (unused).
  601. 0, // file attributes.
  602. FILE_SHARE_READ | FILE_SHARE_WRITE,
  603. FILE_OVERWRITE_IF, // create disposition.
  604. 0, // create options.
  605. NULL,
  606. 0
  607. );
  608. if ( !NT_SUCCESS( Status ) ) {
  609. ICA_FREE_POOL( TraceString.Buffer );
  610. return( Status );
  611. }
  612. /*
  613. * Use the trace file handle to get a pointer to the file object.
  614. */
  615. Status = ObReferenceObjectByHandle(
  616. TraceFileHandle,
  617. 0L, // DesiredAccess
  618. *IoFileObjectType,
  619. KernelMode,
  620. (PVOID *)&pTraceFileObject,
  621. NULL
  622. );
  623. ZwClose( TraceFileHandle );
  624. if ( !NT_SUCCESS( Status ) ) {
  625. ICA_FREE_POOL( TraceString.Buffer );
  626. return( Status );
  627. }
  628. /*
  629. * Save Trace file name and file object pointer
  630. */
  631. pTraceInfo->pTraceFileName = TraceString.Buffer;
  632. pTraceInfo->pTraceFileObject = pTraceFileObject;
  633. return( STATUS_SUCCESS );
  634. }
  635. /*******************************************************************************
  636. *
  637. * _IcaCloseTraceFile
  638. *
  639. * Close a trace file
  640. *
  641. * ENTRY:
  642. * pTraceInfo (input)
  643. * pointer to ICA_TRACE_INFO struct
  644. *
  645. * EXIT:
  646. * STATUS_SUCCESS - no error
  647. *
  648. ******************************************************************************/
  649. VOID
  650. _IcaCloseTraceFile(
  651. IN PICA_TRACE_INFO pTraceInfo
  652. )
  653. {
  654. PWCHAR pTraceFileName;
  655. PFILE_OBJECT pTraceFileObject;
  656. /*
  657. * First write out any deferred trace records that exist
  658. */
  659. _IcaFlushDeferredTrace( pTraceInfo );
  660. /*
  661. * Get/reset trace info fields
  662. */
  663. pTraceFileName = pTraceInfo->pTraceFileName;
  664. pTraceFileObject = pTraceInfo->pTraceFileObject;
  665. pTraceInfo->pTraceFileName = NULL;
  666. pTraceInfo->pTraceFileObject = NULL;
  667. /*
  668. * Close trace file and free resources
  669. */
  670. ICA_FREE_POOL( pTraceFileName );
  671. ObDereferenceObject( pTraceFileObject );
  672. }
  673. /*******************************************************************************
  674. *
  675. * _IcaTraceWrite
  676. *
  677. * Write a trace file entry
  678. *
  679. * ENTRY:
  680. * pTraceInfo (input)
  681. * pointer to ICA_TRACE_INFO struct
  682. * Buffer (input)
  683. * pointer to trace buffer to write
  684. *
  685. * EXIT:
  686. * nothing
  687. *
  688. ******************************************************************************/
  689. VOID
  690. _IcaTraceWrite(
  691. IN PICA_TRACE_INFO pTraceInfo,
  692. IN PVOID Buffer
  693. )
  694. {
  695. KIRQL irql;
  696. ULONG Length;
  697. PDEFERRED_TRACE pDeferred;
  698. PDEFERRED_TRACE *ppDeferredTrace;
  699. NTSTATUS Status;
  700. /*
  701. * Write to kernel debugger if necessary
  702. */
  703. if ( pTraceInfo->fTraceDebugger )
  704. DbgPrint( "%s", Buffer );
  705. /*
  706. * If no file object pointer, then we're done
  707. */
  708. if ( pTraceInfo->pTraceFileObject == NULL )
  709. return;
  710. Length = strlen(Buffer);
  711. /*
  712. * If current Irql is DISPATCH_LEVEL or higher, then we can't
  713. * write the data now, so queue it for later writing.
  714. */
  715. irql = KeGetCurrentIrql();
  716. if ( irql >= DISPATCH_LEVEL ) {
  717. KIRQL oldIrql;
  718. /*
  719. * Allocate and initialize a deferred trace entry
  720. */
  721. pDeferred = ICA_ALLOCATE_POOL( NonPagedPool, sizeof(*pDeferred) + Length );
  722. if ( pDeferred == NULL )
  723. return;
  724. pDeferred->Next = NULL;
  725. pDeferred->Length = Length;
  726. RtlCopyMemory( pDeferred->Buffer, Buffer, Length );
  727. /*
  728. * Since the deferred list may be manipulated in
  729. * _IcaFlushDeferredTrace on behalf of an IOCTL_SYSTEM_TRACE
  730. * which does not hold any locks, IcaSpinLock is used to
  731. * ensure the list's integrity.
  732. */
  733. IcaAcquireSpinLock( &IcaTraceSpinLock, &oldIrql );
  734. /*
  735. * Add it to the end of the list
  736. */
  737. ppDeferredTrace = &pTraceInfo->pDeferredTrace;
  738. while ( *ppDeferredTrace )
  739. ppDeferredTrace = &(*ppDeferredTrace)->Next;
  740. *ppDeferredTrace = pDeferred;
  741. IcaReleaseSpinLock( &IcaTraceSpinLock, oldIrql );
  742. return;
  743. }
  744. /*
  745. * Write out any deferred trace records that exist
  746. */
  747. _IcaFlushDeferredTrace( pTraceInfo );
  748. /*
  749. * Now write the current trace buffer
  750. */
  751. CtxWriteFile( pTraceInfo->pTraceFileObject, Buffer, Length, NULL, NULL, NULL );
  752. }
  753. /*******************************************************************************
  754. *
  755. * _IcaFlushDeferredTrace
  756. *
  757. * Write any deferred trace file entries
  758. *
  759. * ENTRY:
  760. * pTraceInfo (input)
  761. * pointer to ICA_TRACE_INFO struct
  762. *
  763. * EXIT:
  764. * nothing
  765. *
  766. ******************************************************************************/
  767. VOID
  768. _IcaFlushDeferredTrace( PICA_TRACE_INFO pTraceInfo )
  769. {
  770. KIRQL oldIrql;
  771. PDEFERRED_TRACE pDeferred;
  772. IcaAcquireSpinLock( &IcaTraceSpinLock, &oldIrql );
  773. while ( (pDeferred = pTraceInfo->pDeferredTrace) ) {
  774. pTraceInfo->pDeferredTrace = pDeferred->Next;
  775. IcaReleaseSpinLock( &IcaTraceSpinLock, oldIrql );
  776. CtxWriteFile( pTraceInfo->pTraceFileObject, pDeferred->Buffer,
  777. pDeferred->Length, NULL, NULL, NULL );
  778. ICA_FREE_POOL( pDeferred );
  779. IcaAcquireSpinLock( &IcaTraceSpinLock, &oldIrql );
  780. }
  781. IcaReleaseSpinLock( &IcaTraceSpinLock, oldIrql );
  782. }
  783. /*******************************************************************************
  784. *
  785. * _FormatTime
  786. *
  787. * format current time into buffer
  788. *
  789. * ENTRY:
  790. * pBuffer (output)
  791. * pointer to buffer
  792. * Length (input)
  793. * length of buffer
  794. *
  795. * EXIT:
  796. * length of formated time
  797. *
  798. ******************************************************************************/
  799. int
  800. _FormatTime( CHAR * pBuffer, ULONG Length )
  801. {
  802. LARGE_INTEGER SystemTime;
  803. LARGE_INTEGER LocalTime;
  804. TIME_FIELDS TimeFields;
  805. int len;
  806. /*
  807. * Get local time
  808. */
  809. KeQuerySystemTime( &SystemTime );
  810. ExSystemTimeToLocalTime( &SystemTime, &LocalTime );
  811. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  812. /*
  813. * Format buffer
  814. */
  815. len = _snprintf( pBuffer,
  816. Length,
  817. "%02d:%02d:%02d.%03d ",
  818. TimeFields.Hour,
  819. TimeFields.Minute,
  820. TimeFields.Second,
  821. TimeFields.Milliseconds );
  822. return( len );
  823. }
  824. /*******************************************************************************
  825. *
  826. * _FormatThreadId
  827. *
  828. * format thread id into buffer
  829. *
  830. * ENTRY:
  831. * pBuffer (output)
  832. * pointer to buffer
  833. * Length (input)
  834. * length of buffer
  835. *
  836. * EXIT:
  837. * length of formated time
  838. *
  839. ******************************************************************************/
  840. #define TEB_CLIENTID_OFFSET 0x1e0
  841. int
  842. _FormatThreadId( CHAR * pBuffer, ULONG Length )
  843. {
  844. PCLIENT_ID pClientId;
  845. char Number[40]; //on IA64, %p is 16 chars, we need two of these. So 32 + 2 bytes for "." and "\0". Use 40 just in case
  846. int len;
  847. /*
  848. * Get pointer to clientid structure in teb
  849. * - use hardcoded teb offset
  850. */
  851. pClientId = (PCLIENT_ID) ((char*)PsGetCurrentThread() + TEB_CLIENTID_OFFSET);
  852. /*
  853. * Format buffer
  854. */
  855. _snprintf( Number, sizeof(Number), "%p.%p",
  856. pClientId->UniqueProcess, pClientId->UniqueThread );
  857. len = _snprintf( pBuffer, Length, "%-7s ", Number );
  858. return( len );
  859. }
  860. /*******************************************************************************
  861. *
  862. * _WriteHexData
  863. *
  864. * format and write hex data
  865. *
  866. * ENTRY:
  867. * pTraceInfo (input)
  868. * pointer to ICA_TRACE_INFO struct
  869. * pBuffer (output)
  870. * pointer to buffer
  871. * Length (input)
  872. * length of buffer
  873. *
  874. * EXIT:
  875. * length of formated time
  876. *
  877. ******************************************************************************/
  878. VOID
  879. _WriteHexData(
  880. IN PICA_TRACE_INFO pTraceInfo,
  881. IN PVOID pBuffer,
  882. IN ULONG ByteCount
  883. )
  884. {
  885. PUCHAR pData;
  886. ULONG i;
  887. ULONG j;
  888. char Buffer[256];
  889. /*
  890. * Output data
  891. */
  892. pData = (PUCHAR) pBuffer;
  893. for ( i=0; i < ByteCount; i += 16 ) {
  894. ULONG c = 0;
  895. for ( j=0; j < 16 && (i+j) < ByteCount; j++ )
  896. c += _snprintf( &Buffer[c], sizeof(Buffer)-c, "%02X ", pData[j] );
  897. for ( ; j < 16; j++ ) {
  898. Buffer[c++] = ' ';
  899. Buffer[c++] = ' ';
  900. Buffer[c++] = ' ';
  901. }
  902. Buffer[c++] = ' ';
  903. Buffer[c++] = ' ';
  904. for ( j=0; j < 16 && (i+j) < ByteCount; j++, pData++ ) {
  905. if ( *pData < 0x20 || *pData > 0x7f )
  906. Buffer[c++] = '.';
  907. else
  908. Buffer[c++] = *pData;
  909. }
  910. Buffer[c++] = '\n';
  911. Buffer[c++] = '\0';
  912. _IcaTraceWrite( pTraceInfo, Buffer );
  913. }
  914. }