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.

5287 lines
140 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Debug.cpp
  7. //
  8. // Description:
  9. // Debugging utilities.
  10. //
  11. // Documentation:
  12. // Spec\Admin\Debugging.ppt
  13. //
  14. // Maintained By:
  15. // Geoffrey Pease (GPease) 22-NOV-1999
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "pch.h"
  19. #include <shlwapi.h>
  20. //
  21. // Why aren't these in SHLWAPI?
  22. //
  23. #if ! defined( StrLen )
  24. #define StrLen( _sz ) lstrlen( _sz )
  25. #endif // ! defined( StrLen )
  26. #if ! defined( StrLenA )
  27. #define StrLenA( _sz ) lstrlenA( _sz )
  28. #endif // ! defined( StrLenA )
  29. #if ! defined( StrLenW )
  30. #define StrLenW( _sz ) lstrlenW( _sz )
  31. #endif // ! defined( StrLenW )
  32. #if defined( DEBUG )
  33. //
  34. // Include the WINERROR, HRESULT and NTSTATUS codes
  35. //
  36. #include <winerror.dbg>
  37. //#include <ntstatus.dbg>
  38. //
  39. // Constants
  40. //
  41. static const int cchDEBUG_OUTPUT_BUFFER_SIZE = 512;
  42. static const int cchFILEPATHLINESIZE = 85;
  43. //
  44. // Globals
  45. //
  46. DWORD g_TraceMemoryIndex = -1;
  47. DWORD g_TraceFlagsIndex = -1;
  48. DWORD g_ThreadCounter = 0;
  49. DWORD g_dwCounter = 0;
  50. TRACEFLAG g_tfModule = mtfNEVER;
  51. LONG g_lDebugSpinLock = FALSE;
  52. //
  53. // Strings
  54. //
  55. static const TCHAR g_szNULL[] = TEXT("");
  56. static const TCHAR g_szTrue[] = TEXT("True");
  57. static const TCHAR g_szFalse[] = TEXT("False");
  58. static const TCHAR g_szFileLine[] = TEXT("%s(%u):");
  59. static const TCHAR g_szFormat[] = TEXT("%-60s %-10.10s ");
  60. static const TCHAR g_szUnknown[] = TEXT("<unknown>");
  61. //
  62. // ImageHlp Stuff - not ready for prime time yet.
  63. //
  64. #if defined(IMAGEHLP_ENABLED)
  65. //
  66. // ImageHelp
  67. //
  68. typedef VOID (*PFNRTLGETCALLERSADDRESS)(PVOID*,PVOID*);
  69. HINSTANCE g_hImageHlp = NULL;
  70. PFNSYMGETSYMFROMADDR g_pfnSymGetSymFromAddr = NULL;
  71. PFNSYMGETLINEFROMADDR g_pfnSymGetLineFromAddr = NULL;
  72. PFNSYMGETMODULEINFO g_pfnSymGetModuleInfo = NULL;
  73. PFNRTLGETCALLERSADDRESS g_pfnRtlGetCallersAddress = NULL;
  74. #endif // IMAGEHLP_ENABLED
  75. //
  76. // Per thread structure.
  77. //
  78. typedef struct _SPERTHREADDEBUG {
  79. DWORD dwFlags;
  80. DWORD dwStackCounter;
  81. } SPerThreadDebug;
  82. //****************************************************************************
  83. //
  84. // WMI Tracing Routines
  85. //
  86. // These routines are only in the DEBUG version.
  87. //
  88. //****************************************************************************
  89. //////////////////////////////////////////////////////////////////////////////
  90. //++
  91. //
  92. // void
  93. // DebugDumpWMITraceFlags(
  94. // DEBUG_WMI_CONTROL_GUIDS * pdwcgIn
  95. // )
  96. //
  97. // Description:
  98. // Dumps the currently set flags.
  99. //
  100. // Arguments:
  101. // pdwcgIn - Pointer to the DEBUG_WMI_CONTROL_GUIDS to explore.
  102. //
  103. // Return Values:
  104. // None.
  105. //
  106. //--
  107. //////////////////////////////////////////////////////////////////////////////
  108. void
  109. DebugDumpWMITraceFlags(
  110. DEBUG_WMI_CONTROL_GUIDS * pdwcgIn
  111. )
  112. {
  113. DWORD dwFlag;
  114. signed int nCount;
  115. if ( pdwcgIn->pMapFlagsToComments == NULL )
  116. {
  117. DebugMsg( "DEBUG: no flag mappings available.\n" );
  118. return; // NOP
  119. } // if: no mapping table
  120. dwFlag = 0x80000000;
  121. for ( nCount = 31; nCount >= 0; nCount-- )
  122. {
  123. if ( pdwcgIn->dwFlags & dwFlag )
  124. {
  125. DebugMsg( "DEBUG: 0x%08x = %s\n",
  126. dwFlag,
  127. ( pdwcgIn->pMapFlagsToComments[ nCount ].pszName != NULL ? pdwcgIn->pMapFlagsToComments[ nCount ].pszName : g_szUnknown )
  128. );
  129. } // if: flag set
  130. dwFlag = dwFlag >> 1;
  131. } // for: nCount
  132. } //*** DebugDumpWMITraceFlags( )
  133. //****************************************************************************
  134. //
  135. // Debugging and Tracing Routines
  136. //
  137. //****************************************************************************
  138. //////////////////////////////////////////////////////////////////////////////
  139. //
  140. // void
  141. // DebugIncrementStackDepthCounter( void )
  142. //
  143. // Description:
  144. // Increases the stack scope depth counter. If "per thread" tracking is
  145. // on it will increment the "per thread" counter. Otherwise, it will
  146. // increment the "global" counter.
  147. //
  148. // Arguments:
  149. // None.
  150. //
  151. // Return Values:
  152. // None.
  153. //
  154. //////////////////////////////////////////////////////////////////////////////
  155. void
  156. DebugIncrementStackDepthCounter( void )
  157. {
  158. if ( g_tfModule & mtfPERTHREADTRACE )
  159. {
  160. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  161. if ( ptd != NULL )
  162. {
  163. ptd->dwStackCounter++;
  164. } // if: ptd
  165. } // if: per thread
  166. else
  167. {
  168. InterlockedIncrement( (LONG*) &g_dwCounter );
  169. } // else: global
  170. } // DebugIncrementStackDepthCounter( )
  171. //////////////////////////////////////////////////////////////////////////////
  172. //++
  173. //
  174. // void
  175. // DebugDecrementStackDepthCounter( void )
  176. //
  177. // Description:
  178. // Decreases the stack scope depth counter. If "per thread" tracking is
  179. // on it will decrement the "per thread" counter. Otherwise, it will
  180. // decrement the "global" counter.
  181. //
  182. // Arguments:
  183. // None.
  184. //
  185. // Return Values:
  186. // None.
  187. //
  188. //--
  189. //////////////////////////////////////////////////////////////////////////////
  190. void
  191. DebugDecrementStackDepthCounter( void )
  192. {
  193. if ( g_tfModule & mtfPERTHREADTRACE )
  194. {
  195. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  196. if ( ptd != NULL )
  197. {
  198. ptd->dwStackCounter--;
  199. } // if: ptd
  200. } // if: per thread
  201. else
  202. {
  203. InterlockedDecrement( (LONG*) &g_dwCounter );
  204. } // else: global
  205. } // DebugDecrementStackDepthCounter( )
  206. //////////////////////////////////////////////////////////////////////////////
  207. //++
  208. //
  209. // void
  210. // DebugAcquireSpinLock(
  211. // LONG * pLock
  212. // )
  213. //
  214. // Description:
  215. // Acquires the spin lock pointed to by pLock.
  216. //
  217. // Arguments:
  218. // pLock - Pointer to the spin lock.
  219. //
  220. // Return Values:
  221. // None.
  222. //
  223. //--
  224. //////////////////////////////////////////////////////////////////////////////
  225. void
  226. DebugAcquireSpinLock(
  227. LONG * pLock
  228. )
  229. {
  230. for(;;)
  231. {
  232. LONG lInitialValue;
  233. lInitialValue = InterlockedCompareExchange( pLock, TRUE, FALSE );
  234. if ( lInitialValue == FALSE )
  235. {
  236. //
  237. // Lock acquired.
  238. //
  239. break;
  240. } // if: got lock
  241. else
  242. {
  243. //
  244. // Sleep to give other thread a chance to give up the lock.
  245. //
  246. Sleep( 1 );
  247. } // if: lock not acquired
  248. } // for: forever
  249. } // DebugAcquireSpinLock( )
  250. //////////////////////////////////////////////////////////////////////////////
  251. //++
  252. //
  253. // void
  254. // DebugReleaseSpinLock(
  255. // LONG * pLock
  256. // )
  257. //
  258. // Description:
  259. // Releases the spin lock pointer to by pLock.
  260. //
  261. // Arguments:
  262. // pLock - Pointer to the spin lock.
  263. //
  264. // Return Values:
  265. // None.
  266. //
  267. //--
  268. //////////////////////////////////////////////////////////////////////////////
  269. void
  270. DebugReleaseSpinLock(
  271. LONG * pLock
  272. )
  273. {
  274. *pLock = FALSE;
  275. } // DebugReleaseSpinLock( )
  276. //////////////////////////////////////////////////////////////////////////////
  277. //++
  278. //
  279. // BOOL
  280. // IsDebugFlagSet(
  281. // TRACEFLAG tfIn
  282. // )
  283. //
  284. // Description:
  285. // Checks the global g_tfModule and the "per thread" Trace Flags to
  286. // determine if the flag (any of the flags) are turned on.
  287. //
  288. // Arguments:
  289. // tfIn - Trace flags to compare.
  290. //
  291. // Return Values:
  292. // TRUE At least of one of the flags are present.
  293. // FALSE None of the flags match.
  294. //
  295. //--
  296. //////////////////////////////////////////////////////////////////////////////
  297. BOOL
  298. IsDebugFlagSet(
  299. TRACEFLAG tfIn
  300. )
  301. {
  302. if ( g_tfModule & tfIn )
  303. {
  304. return TRUE;
  305. } // if: global flag set
  306. if ( g_tfModule & mtfPERTHREADTRACE )
  307. {
  308. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  309. if ( ptd != NULL
  310. && ptd->dwFlags & tfIn
  311. )
  312. {
  313. return TRUE;
  314. } // if: per thread flag set
  315. } // if: per thread settings
  316. return FALSE;
  317. } //*** IsDebugFlagSet( )
  318. //////////////////////////////////////////////////////////////////////////////
  319. //++
  320. //
  321. // void
  322. // DebugOutputString(
  323. // LPCTSTR pszIn
  324. // )
  325. //
  326. // Description:
  327. // Dumps the spew to the appropriate orafice.
  328. //
  329. // Arguments:
  330. // pszIn Message to dump.
  331. //
  332. // Return Values:
  333. // None.
  334. //
  335. //--
  336. //////////////////////////////////////////////////////////////////////////////
  337. void
  338. DebugOutputString(
  339. LPCTSTR pszIn
  340. )
  341. {
  342. if ( IsTraceFlagSet( mtfOUTPUTTODISK ) )
  343. {
  344. LogMsg( pszIn );
  345. } // if: log to file
  346. else
  347. {
  348. DebugAcquireSpinLock( &g_lDebugSpinLock );
  349. OutputDebugString( pszIn );
  350. DebugReleaseSpinLock( &g_lDebugSpinLock );
  351. } // else: debugger
  352. } //*** DebugOutputString( )
  353. #if 0
  354. /*
  355. //////////////////////////////////////////////////////////////////////////////
  356. //++
  357. // void
  358. // DebugFindNTStatusSymbolicName(
  359. // DWORD dwStatusIn,
  360. // LPTSTR pszNameOut,
  361. // LPDWORD pcchNameInout
  362. // )
  363. //
  364. // Description:
  365. // Uses the NTBUILD generated ntstatusSymbolicNames table to lookup
  366. // the symbolic name for the status code. The name will be returned in
  367. // pszNameOut. pcchNameInout should indicate the size of the buffer that
  368. // pszNameOut points too. pcchNameInout will return the number of
  369. // characters copied out.
  370. //
  371. // Arguments:
  372. // dwStatusIn - Status code to lookup.
  373. // pszNameOut - Buffer to store the string name
  374. // pcchNameInout - The length of the buffer in and the size out.
  375. //
  376. // Return Values:
  377. // None.
  378. //
  379. //--
  380. //////////////////////////////////////////////////////////////////////////////
  381. void
  382. DebugFindNTStatusSymbolicName(
  383. NTSTATUS dwStatusIn,
  384. LPTSTR pszNameOut,
  385. LPDWORD pcchNameInout
  386. )
  387. {
  388. Assert( pszNameOut != NULL );
  389. Assert( pcchNameInout != NULL );
  390. int idx = 0;
  391. while ( ntstatusSymbolicNames[ idx ].SymbolicName
  392. )
  393. {
  394. if ( ntstatusSymbolicNames[ idx ].MessageId == dwStatusIn
  395. )
  396. {
  397. #if defined ( UNICODE )
  398. *pcchNameInout = mbstowcs( pszNameOut, ntstatusSymbolicNames[ idx ].SymbolicName, *pcchNameInout );
  399. Assert( *pcchNameInout != -1 );
  400. #else // ASCII
  401. StrCpyN( pszNameOut, ntstatusSymbolicNames[ idx ].SymbolicName, *pcchNameInout );
  402. *pcchNameInout = StrLen( pszNameOut );
  403. #endif // UNICODE
  404. return;
  405. } // if: matched
  406. idx++;
  407. } // while: entries in list
  408. //
  409. // If we made it here, we did not find an entry.
  410. //
  411. StrCpyN( pszNameOut, TEXT("<unknown>"), *pcchNameInout );
  412. *pcchNameInout = StrLen( pszNameOut );
  413. return;
  414. } //*** DebugFindNTStatusSymbolicName( )
  415. */
  416. #endif
  417. //////////////////////////////////////////////////////////////////////////////
  418. //++
  419. // void
  420. // DebugFindWinerrorSymbolicName(
  421. // DWORD dwErrIn,
  422. // LPTSTR pszNameOut,
  423. // LPDWORD pcchNameInout
  424. // )
  425. //
  426. // Description:
  427. // Uses the NTBUILD generated winerrorSymbolicNames table to lookup
  428. // the symbolic name for the error code. The name will be returned in
  429. // pszNameOut. pcchNameInout should indicate the size of the buffer that
  430. // pszNameOut points too. pcchNameInout will return the number of
  431. // characters copied out.
  432. //
  433. // Arguments:
  434. // dwErrIn - Error code to lookup.
  435. // pszNameOut - Buffer to store the string name
  436. // pcchNameInout - The length of the buffer in and the size out.
  437. //
  438. // Return Values:
  439. // None.
  440. //
  441. //--
  442. //////////////////////////////////////////////////////////////////////////////
  443. void
  444. DebugFindWinerrorSymbolicName(
  445. DWORD dwErrIn,
  446. LPTSTR pszNameOut,
  447. LPDWORD pcchNameInout
  448. )
  449. {
  450. Assert( pszNameOut != NULL );
  451. Assert( pcchNameInout != NULL );
  452. int idx = 0;
  453. DWORD scode;
  454. //
  455. // If this is a Win32 wrapped in HRESULT stuff, remove the
  456. // HRESULT stuff so that the code will be found in the table.
  457. //
  458. if ( SCODE_FACILITY( dwErrIn ) == FACILITY_WIN32 )
  459. {
  460. scode = SCODE_CODE( dwErrIn );
  461. } // if: Win32 error code
  462. else
  463. {
  464. scode = dwErrIn;
  465. } // else: not Win32 error code
  466. while ( winerrorSymbolicNames[ idx ].SymbolicName )
  467. {
  468. if ( winerrorSymbolicNames[ idx ].MessageId == scode )
  469. {
  470. #if defined ( UNICODE )
  471. *pcchNameInout = mbstowcs( pszNameOut, winerrorSymbolicNames[ idx ].SymbolicName, *pcchNameInout );
  472. Assert( *pcchNameInout != -1 );
  473. #else // ASCII
  474. StrCpyN( pszNameOut, winerrorSymbolicNames[ idx ].SymbolicName, *pcchNameInout );
  475. *pcchNameInout = StrLen( pszNameOut );
  476. #endif // UNICODE
  477. return;
  478. } // if: matched
  479. idx++;
  480. } // while: entries in list
  481. //
  482. // If we made it here, we did not find an entry.
  483. //
  484. StrCpyN( pszNameOut, TEXT("<unknown>"), *pcchNameInout );
  485. *pcchNameInout = StrLen( pszNameOut );
  486. return;
  487. } //*** DebugFindWinerrorSymbolicName( )
  488. //////////////////////////////////////////////////////////////////////////////
  489. //++
  490. //
  491. // void
  492. // DebugReturnMessage(
  493. // LPCTSTR pszFileIn,
  494. // const int nLineIn,
  495. // LPCTSTR pszModuleIn,
  496. // LPTSTR pszBufIn,
  497. // INT * pcchInout,
  498. // LPTSTR * ppszBufOut
  499. // )
  500. //
  501. // Description:
  502. // Prints the spew for a function return with error code.
  503. //
  504. // The primary reason for doing this is to isolate the stack from adding
  505. // the extra size of szSymbolicName to every function.
  506. //
  507. // Argument:
  508. // pszFileIn - File path to insert
  509. // nLineIn - Line number to insert
  510. // pszModuleIn - Module name to insert
  511. // pszBufIn - The buffer to initialize
  512. // pcchInout - IN: Size of the buffer in pszBufIn
  513. // - OUT: Remaining characters in buffer not used.
  514. // ppszBufOut - Next location to write to append more text
  515. //
  516. // Return Values:
  517. // None.
  518. //
  519. //--
  520. //////////////////////////////////////////////////////////////////////////////
  521. void
  522. DebugReturnMessage(
  523. LPCTSTR pszFileIn,
  524. const int nLineIn,
  525. LPCTSTR pszModuleIn,
  526. LPCTSTR pszMessageIn,
  527. DWORD dwErrIn
  528. )
  529. {
  530. TCHAR szSymbolicName[ 64 ]; // random
  531. DWORD cchSymbolicName;
  532. cchSymbolicName = sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] );
  533. DebugFindWinerrorSymbolicName( dwErrIn, szSymbolicName, &cchSymbolicName );
  534. Assert( cchSymbolicName != sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] ) );
  535. TraceMessage( pszFileIn, nLineIn, pszModuleIn, mtfFUNC, pszMessageIn, dwErrIn, szSymbolicName );
  536. } //*** DebugReturnMessage( )
  537. //////////////////////////////////////////////////////////////////////////////
  538. //++
  539. //
  540. // void
  541. // DebugInitializeBuffer(
  542. // LPCTSTR pszFileIn,
  543. // const int nLineIn,
  544. // LPCTSTR pszModuleIn,
  545. // LPTSTR pszBufIn,
  546. // INT * pcchInout,
  547. // LPTSTR * ppszBufOut
  548. // )
  549. //
  550. // Description:
  551. // Intializes the output buffer with "File(Line) Module ".
  552. //
  553. // Argument:
  554. // pszFileIn - File path to insert
  555. // nLineIn - Line number to insert
  556. // pszModuleIn - Module name to insert
  557. // pszBufIn - The buffer to initialize
  558. // pcchInout - IN: Size of the buffer in pszBufIn
  559. // - OUT: Remaining characters in buffer not used.
  560. // ppszBufOut - Next location to write to append more text
  561. //
  562. // Return Values:
  563. // None.
  564. //
  565. //--
  566. //////////////////////////////////////////////////////////////////////////////
  567. void
  568. DebugInitializeBuffer(
  569. LPCTSTR pszFileIn,
  570. const int nLineIn,
  571. LPCTSTR pszModuleIn,
  572. LPTSTR pszBufIn,
  573. INT * pcchInout,
  574. LPTSTR * ppszBufOut
  575. )
  576. {
  577. INT cch = 0;
  578. static TCHAR szBarSpace[] =
  579. TEXT("| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ");
  580. // 1 2 3 4 5
  581. // 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
  582. //
  583. // Add date/time stamp
  584. //
  585. if ( IsTraceFlagSet( mtfADDTIMEDATE ) )
  586. {
  587. static TCHAR szBuffer[ 25 ];
  588. static SYSTEMTIME OldSystemTime = { 0 };
  589. SYSTEMTIME SystemTime;
  590. int iCmp;
  591. GetLocalTime( &SystemTime );
  592. //
  593. // Avoid expensive printf by comparing times
  594. //
  595. iCmp = memcmp( (PVOID)&SystemTime, (PVOID)&OldSystemTime, sizeof( SYSTEMTIME ) );
  596. if ( iCmp != 0 )
  597. {
  598. cch = wnsprintf( szBuffer,
  599. 25,
  600. TEXT("%02u/%02u/%04u %02u:%02u:%02u.%03u "),
  601. SystemTime.wMonth,
  602. SystemTime.wDay,
  603. SystemTime.wYear,
  604. SystemTime.wHour,
  605. SystemTime.wMinute,
  606. SystemTime.wSecond,
  607. SystemTime.wMilliseconds
  608. );
  609. if ( cch != 24 )
  610. {
  611. DEBUG_BREAK; // can't assert!
  612. } // if: cch != 24
  613. } // if: didn't match
  614. StrCpy( pszBufIn, szBuffer );
  615. cch = 24;
  616. } // if: time/date
  617. else
  618. {
  619. //
  620. // Add the filepath and line number
  621. //
  622. if ( pszFileIn != NULL )
  623. {
  624. LPTSTR psz;
  625. cch = wnsprintf( pszBufIn, *pcchInout, g_szFileLine, pszFileIn, nLineIn );
  626. if ( cch < 0 )
  627. {
  628. cch = StrLen( pszBufIn );
  629. } // if: error
  630. for ( psz = pszBufIn + cch; cch < cchFILEPATHLINESIZE; cch++ )
  631. {
  632. *psz = 32;
  633. psz++;
  634. } // for: cch < 60
  635. *psz = 0;
  636. if ( cch != cchFILEPATHLINESIZE )
  637. {
  638. DEBUG_BREAK; // can't assert!
  639. } // if: cch != cchFILEPATHLINESIZE
  640. } // if: have a filepath
  641. } // else: normal (no time/date)
  642. //
  643. // Add module name
  644. //
  645. if ( IsTraceFlagSet( mtfBYMODULENAME ) )
  646. {
  647. if ( pszModuleIn == NULL )
  648. {
  649. StrCpy( pszBufIn + cch, g_szUnknown );
  650. cch += sizeof( g_szUnknown ) / sizeof( g_szUnknown[ 0 ] ) - 1;
  651. } // if:
  652. else
  653. {
  654. static LPCTSTR pszLastTime = NULL;
  655. static DWORD cchLastTime = 0;
  656. StrCpy( pszBufIn + cch, pszModuleIn );
  657. if ( pszLastTime != pszModuleIn )
  658. {
  659. pszLastTime = pszModuleIn;
  660. cchLastTime = StrLen( pszModuleIn );
  661. } // if: not the same as last time
  662. cch += cchLastTime;
  663. } // else:
  664. StrCat( pszBufIn + cch, TEXT(": ") );
  665. cch += 2;
  666. } // if: add module name
  667. //
  668. // Add the thread id if "per thread" tracing is on.
  669. //
  670. if ( g_tfModule & mtfPERTHREADTRACE )
  671. {
  672. //
  673. // And check the "per thread" to see if this particular thread
  674. // is supposed to be displaying its ID.
  675. //
  676. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  677. if ( ptd != NULL
  678. && ptd->dwFlags & mtfPERTHREADTRACE
  679. )
  680. {
  681. int cchPlus;
  682. cchPlus = wnsprintf( pszBufIn + cch,
  683. *pcchInout - cch,
  684. TEXT("~%08x~ "),
  685. GetCurrentThreadId( )
  686. );
  687. if ( cchPlus < 0 )
  688. {
  689. cch = StrLen( pszBufIn );
  690. } // if: failure
  691. else
  692. {
  693. cch += cchPlus;
  694. } // else: success
  695. } // if: turned on in the thread
  696. } // if: tracing by thread
  697. *ppszBufOut = pszBufIn + cch;
  698. *pcchInout -= cch;
  699. //
  700. // Add the "Bar Space" for stack scoping
  701. //
  702. // There must be something to output, both flags must be set,
  703. // and there must to be a filepath.
  704. if ( IsDebugFlagSet( mtfSTACKSCOPE )
  705. && IsDebugFlagSet( mtfFUNC )
  706. && pszFileIn != NULL
  707. )
  708. {
  709. DWORD dwCounter;
  710. //
  711. // Choose "per thread" or "global" counter.
  712. //
  713. if ( g_tfModule & mtfPERTHREADTRACE )
  714. {
  715. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  716. if ( ptd != NULL )
  717. {
  718. dwCounter = ptd->dwStackCounter;
  719. } // if: ptd
  720. else
  721. {
  722. dwCounter = 0;
  723. } // else: assume nothing
  724. } // if: per thread
  725. else
  726. {
  727. dwCounter = g_dwCounter;
  728. } // else: global counter
  729. if ( dwCounter >= 50 )
  730. {
  731. DEBUG_BREAK; // can't assert!
  732. } // if: dwCounter not vaild
  733. if ( dwCounter > 1
  734. && dwCounter < 50
  735. )
  736. {
  737. INT nCount = ( dwCounter - 1 ) * 2;
  738. StrNCpy( *ppszBufOut, szBarSpace, nCount + 1 ); // extra character for bug in StrNCpyNXW( )
  739. *ppszBufOut += nCount;
  740. *pcchInout -= nCount;
  741. } // if: within range
  742. } // if: stack scoping on
  743. } //*** DebugInitializeBuffer( )
  744. #if defined(IMAGEHLP_ENABLED)
  745. /*
  746. //////////////////////////////////////////////////////////////////////////////
  747. //++
  748. //
  749. // FALSE
  750. // DebugNoOp( void )
  751. //
  752. // Description:
  753. // Returns FALSE. Used to replace ImageHlp routines it they weren't
  754. // loaded or not found.
  755. //
  756. // Arguments:
  757. // None.
  758. //
  759. // Return Values:
  760. // FALSE, always.
  761. //
  762. //--
  763. //////////////////////////////////////////////////////////////////////////////
  764. BOOL
  765. DebugNoOp( void )
  766. {
  767. return FALSE;
  768. } //*** DebugNoOp( )
  769. */
  770. #endif // IMAGEHLP_ENABLED
  771. //////////////////////////////////////////////////////////////////////////////
  772. //++
  773. //
  774. // void
  775. // DebugInitializeTraceFlags( void )
  776. //
  777. // Description:
  778. // Retrieves the default tracing flags for this module from an INI file
  779. // that is named the same as the EXE file (e.g. MMC.EXE -> MMC.INI).
  780. // Typically, this is called from the TraceInitializeProcess() macro.
  781. //
  782. // Arguments:
  783. // None.
  784. //
  785. // Return Values:
  786. // None.
  787. //
  788. //--
  789. //////////////////////////////////////////////////////////////////////////////
  790. void
  791. DebugInitializeTraceFlags( void )
  792. {
  793. TCHAR szSection[ 64 ];
  794. TCHAR szFiles[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  795. TCHAR szPath[ MAX_PATH ];
  796. LPTSTR psz;
  797. DWORD dwLen;
  798. //
  799. // Allocate TLS for memory tracking
  800. //
  801. Assert( g_TraceMemoryIndex == -1 );
  802. g_TraceMemoryIndex = TlsAlloc( );
  803. TlsSetValue( g_TraceMemoryIndex, NULL);
  804. //
  805. // Initialize module trace flags
  806. //
  807. //
  808. // Get the EXEs filename and change the extension to INI.
  809. //
  810. dwLen = GetModuleFileName( NULL, szPath, MAX_PATH );
  811. Assert( dwLen != 0 ); // error in GetModuleFileName
  812. StrCpy( &szPath[ dwLen - 3 ], TEXT("ini") );
  813. g_tfModule = (TRACEFLAG) GetPrivateProfileInt( __MODULE__,
  814. TEXT("TraceFlags"),
  815. 0,
  816. szPath
  817. );
  818. DebugMsg( "DEBUG: Reading %s\n%s: DEBUG: g_tfModule = 0x%08x\n",
  819. szPath,
  820. __MODULE__,
  821. g_tfModule
  822. );
  823. //
  824. // Initialize thread trace flags
  825. //
  826. if ( g_tfModule & mtfPERTHREADTRACE )
  827. {
  828. Assert( g_TraceFlagsIndex == -1 );
  829. g_TraceFlagsIndex = TlsAlloc( );
  830. DebugInitializeThreadTraceFlags( NULL );
  831. } // if: per thread tracing
  832. //
  833. // Force the loading of certain modules
  834. //
  835. GetPrivateProfileString( __MODULE__, TEXT("ForcedDLLsSection"), g_szNULL, szSection, 64, szPath );
  836. ZeroMemory( szFiles, cchDEBUG_OUTPUT_BUFFER_SIZE );
  837. GetPrivateProfileSection( szSection, szFiles, cchDEBUG_OUTPUT_BUFFER_SIZE, szPath );
  838. psz = szFiles;
  839. while ( *psz )
  840. {
  841. TCHAR szExpandedPath[ MAX_PATH ];
  842. ExpandEnvironmentStrings( psz, szExpandedPath, MAX_PATH );
  843. DebugMsg( "DEBUG: Forcing %s to be loaded.\n", szExpandedPath );
  844. LoadLibrary( szExpandedPath );
  845. psz += StrLen( psz ) + 1;
  846. } // while: entry found
  847. #if defined(IMAGEHLP_ENABLED)
  848. /*
  849. //
  850. // Load symbols for our module
  851. //
  852. g_hImageHlp = LoadLibraryEx( TEXT("imagehlp.dll"), NULL, 0 );
  853. if ( g_hImageHlp != NULL )
  854. {
  855. // Typedef this locally since it is only needed once.
  856. typedef BOOL (*PFNSYMINITIALIZE)(HANDLE, PSTR, BOOL);
  857. PFNSYMINITIALIZE pfnSymInitialize;
  858. pfnSymInitialize = (PFNSYMINITIALIZE) GetProcAddress( g_hImageHlp, "SymInitialize" );
  859. if ( pfnSymInitialize != NULL )
  860. {
  861. pfnSymInitialize( GetCurrentProcess( ), NULL, TRUE );
  862. } // if: got address
  863. //
  864. // Grab the other addresses we need. Replace them with a "no op" if they are not found
  865. //
  866. g_pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) GetProcAddress( g_hImageHlp, "SymGetSymFromAddr" );
  867. g_pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress( g_hImageHlp, "SymGetLineFromAddr" );
  868. g_pfnSymGetModuleInfo = (PFNSYMGETMODULEINFO) GetProcAddress( g_hImageHlp, "SymGetModuleInfo" );
  869. } // if: imagehlp loaded
  870. //
  871. // If loading IMAGEHLP failed, we need to point these to the "no op" routine.
  872. //
  873. if ( g_pfnSymGetSymFromAddr == NULL )
  874. {
  875. g_pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) &DebugNoOp;
  876. } // if: failed
  877. if ( g_pfnSymGetLineFromAddr == NULL )
  878. {
  879. g_pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) &DebugNoOp;
  880. } // if: failed
  881. if ( g_pfnSymGetModuleInfo == NULL )
  882. {
  883. g_pfnSymGetModuleInfo = (PFNSYMGETMODULEINFO) &DebugNoOp;
  884. } // if: failed
  885. HINSTANCE hMod = LoadLibrary( TEXT("NTDLL.DLL") );
  886. g_pfnRtlGetCallersAddress = (PFNRTLGETCALLERSADDRESS) GetProcAddress( hMod, "RtlGetCallersAddress" );
  887. if ( g_pfnRtlGetCallersAddress == NULL )
  888. {
  889. g_pfnRtlGetCallersAddress = (PFNRTLGETCALLERSADDRESS) &DebugNoOp;
  890. } // if: failed
  891. */
  892. #endif // IMAGEHLP_ENABLED
  893. } //*** DebugInitializeTraceFlags( )
  894. //////////////////////////////////////////////////////////////////////////////
  895. //++
  896. //
  897. // void
  898. // DebugTerminateProcess( void )
  899. //
  900. // Description:
  901. // Cleans up anything that the debugging routines allocated or
  902. // initialized. Typically, you should call the TraceTerminateProcess()
  903. // macro just before your process exits.
  904. //
  905. // Arguments:
  906. // None.
  907. //
  908. // Return Values:
  909. // None.
  910. //
  911. //--
  912. //////////////////////////////////////////////////////////////////////////////
  913. void
  914. DebugTerminateProcess( void )
  915. {
  916. #if defined(IMAGEHLP_ENABLED)
  917. /*
  918. //
  919. // ImageHlp Cleanup
  920. //
  921. if ( g_hImageHlp != NULL )
  922. {
  923. // Typedef this locally since it is only needed once.
  924. typedef BOOL (*PFNSYMCLEANUP)(HANDLE);
  925. PFNSYMCLEANUP pfnSymCleanup;
  926. pfnSymCleanup = (PFNSYMCLEANUP) GetProcAddress( g_hImageHlp, "SymCleanup" );
  927. if ( pfnSymCleanup != NULL )
  928. {
  929. pfnSymCleanup( GetCurrentProcess( ) );
  930. } // if: found proc
  931. FreeLibrary( g_hImageHlp );
  932. } // if: imagehlp loaded
  933. */
  934. #endif // IMAGEHLP_ENABLED
  935. //
  936. // Free the TLS storage
  937. //
  938. if ( g_tfModule & mtfPERTHREADTRACE )
  939. {
  940. TlsFree( g_TraceFlagsIndex );
  941. } // if: per thread tracing
  942. TlsFree( g_TraceMemoryIndex );
  943. } //*** DebugTerminateProcess( )
  944. #if defined(IMAGEHLP_ENABLED)
  945. /*
  946. //////////////////////////////////////////////////////////////////////////////
  947. //++
  948. //
  949. // void
  950. // DebugGetFunctionName(
  951. // LPSTR pszNameOut,
  952. // DWORD cchNameIn
  953. // )
  954. //
  955. // Description:
  956. // Retrieves the calling functions name.
  957. //
  958. // Arguments:
  959. // pszNameOut - The buffer that will contain the functions name.
  960. // cchNameIn - The size of the the out buffer.
  961. //
  962. // Return Values:
  963. // None.
  964. //
  965. //--
  966. //////////////////////////////////////////////////////////////////////////////
  967. void
  968. DebugGetFunctionName(
  969. LPSTR pszNameOut,
  970. DWORD cchNameIn
  971. )
  972. {
  973. PVOID CallersAddress;
  974. PVOID CallersCaller;
  975. BOOL fSuccess;
  976. union
  977. {
  978. IMAGEHLP_SYMBOL sym;
  979. BYTE buf[ 255 ];
  980. } SymBuf;
  981. SymBuf.sym.SizeOfStruct = sizeof( SymBuf );
  982. g_pfnRtlGetCallersAddress( &CallersAddress, &CallersCaller );
  983. fSuccess = g_pfnSymGetSymFromAddr( GetCurrentProcess( ), (LONG) CallersAddress, 0, (PIMAGEHLP_SYMBOL) &SymBuf );
  984. if ( fSuccess )
  985. {
  986. StrCpyNA( pszNameOut, SymBuf.sym.Name, cchNameIn );
  987. } // if: success
  988. else
  989. {
  990. DWORD dwErr = GetLastError( );
  991. StrCpyNA( pszNameOut, "<unknown>", cchNameIn );
  992. } // if: failed
  993. } //*** DebugGetFunctionName( )
  994. */
  995. #endif // IMAGEHLP_ENABLED
  996. //////////////////////////////////////////////////////////////////////////////
  997. //++
  998. //
  999. // void
  1000. // DebugInitializeThreadTraceFlags(
  1001. // LPCTSTR pszThreadNameIn
  1002. // )
  1003. //
  1004. // Description:
  1005. // If enabled (g_tfModule & mtfPERTHREADTRACE), retrieves the default
  1006. // tracing flags for this thread from an INI file that is named the
  1007. // same as the EXE file (e.g. MMC.EXE -> MMC.INI). The particular
  1008. // TraceFlag level is determined by either the thread name (handed in
  1009. // as a parameter) or by the thread counter ID which is incremented
  1010. // every time a new thread is created and calls this routine. The
  1011. // incremental name is "ThreadTraceFlags%u".
  1012. //
  1013. // This routine is called from the TraceInitliazeThread() macro.
  1014. //
  1015. // Arguments:
  1016. // pszThreadNameIn
  1017. // - If the thread has an assoc. name with it, use it instead of the
  1018. // incremented version. NULL indicate no naming.
  1019. //
  1020. //
  1021. // Return Values:
  1022. // None.
  1023. //
  1024. //--
  1025. //////////////////////////////////////////////////////////////////////////////
  1026. void
  1027. DebugInitializeThreadTraceFlags(
  1028. LPCTSTR pszThreadNameIn
  1029. )
  1030. {
  1031. //
  1032. // Read per thread flags
  1033. //
  1034. if ( g_tfModule & mtfPERTHREADTRACE )
  1035. {
  1036. TCHAR szPath[ MAX_PATH ];
  1037. DWORD dwTraceFlags;
  1038. DWORD dwLen;
  1039. SPerThreadDebug * ptd;
  1040. LPCTSTR pszThreadTraceFlags;
  1041. //
  1042. // Get the EXEs filename and change the extension to INI.
  1043. //
  1044. dwLen = GetModuleFileName( NULL, szPath, sizeof( szPath ) );
  1045. Assert( dwLen != 0 ); // error in GetModuleFileName
  1046. StrCpy( &szPath[ dwLen - 3 ], TEXT("ini") );
  1047. if ( pszThreadNameIn == NULL )
  1048. {
  1049. TCHAR szThreadTraceFlags[ 50 ];
  1050. //
  1051. // No name thread - use generic name
  1052. //
  1053. wnsprintf( szThreadTraceFlags, sizeof( szThreadTraceFlags ), TEXT("ThreadTraceFlags%u"), g_ThreadCounter );
  1054. dwTraceFlags = GetPrivateProfileInt( __MODULE__, szThreadTraceFlags, 0, szPath );
  1055. InterlockedIncrement( (LONG *) &g_ThreadCounter );
  1056. pszThreadTraceFlags = szThreadTraceFlags;
  1057. } // if: no thread name
  1058. else
  1059. {
  1060. //
  1061. // Named thread
  1062. //
  1063. dwTraceFlags = GetPrivateProfileInt( __MODULE__, pszThreadNameIn, 0, szPath );
  1064. pszThreadTraceFlags = pszThreadNameIn;
  1065. } // else: named thread
  1066. Assert( g_TraceFlagsIndex != 0 );
  1067. // don't track this.
  1068. ptd = (SPerThreadDebug *) GlobalAlloc( GMEM_FIXED, sizeof( SPerThreadDebug ) );
  1069. Assert( ptd != NULL );
  1070. ptd->dwFlags = dwTraceFlags;
  1071. ptd->dwStackCounter = 0;
  1072. TlsSetValue( g_TraceFlagsIndex, ptd );
  1073. DebugMsg( "DEBUG: Starting ThreadId = 0x%08x - %s = 0x%08x\n",
  1074. GetCurrentThreadId( ),
  1075. pszThreadTraceFlags,
  1076. dwTraceFlags
  1077. );
  1078. } // if: per thread tracing turned on
  1079. } //*** DebugInitializeThreadTraceFlags( )
  1080. //////////////////////////////////////////////////////////////////////////////
  1081. //++
  1082. //
  1083. // void
  1084. // DebugTerminiateThreadTraceFlags( void )
  1085. //
  1086. // Description:
  1087. // Cleans up the mess create by DebugInitializeThreadTraceFlags( ). One
  1088. // should use the TraceTerminateThread( ) macro instead of calling this
  1089. // directly.
  1090. //
  1091. // Arguments:
  1092. // None.
  1093. //
  1094. // Return Values:
  1095. // None.
  1096. //
  1097. //--
  1098. //////////////////////////////////////////////////////////////////////////////
  1099. void
  1100. DebugTerminiateThreadTraceFlags( void )
  1101. {
  1102. //
  1103. // If "per thread" is on, clean up the memory allocation.
  1104. //
  1105. if ( g_tfModule & mtfPERTHREADTRACE )
  1106. {
  1107. Assert( g_TraceFlagsIndex != -1 );
  1108. SPerThreadDebug * ptd = (SPerThreadDebug *) TlsGetValue( g_TraceFlagsIndex );
  1109. if ( ptd != NULL )
  1110. {
  1111. GlobalFree( ptd );
  1112. TlsSetValue( g_TraceFlagsIndex, NULL );
  1113. } // if: ptd
  1114. } // if: per thread
  1115. } // DebugTerminiateThreadTraceFlags( )
  1116. //////////////////////////////////////////////////////////////////////////////
  1117. //++
  1118. //
  1119. // ASCII version
  1120. //
  1121. // void
  1122. // TraceMsg(
  1123. // TRACEFLAG tfIn,
  1124. // LPCSTR pszFormatIn,
  1125. // ...
  1126. // )
  1127. //
  1128. // Description:
  1129. // If any of the flags in trace flags match any of the flags set in
  1130. // tfIn, the formatted string will be printed to the debugger.
  1131. //
  1132. // Arguments:
  1133. // tfIn - Flags to be checked.
  1134. // pszFormatIn - Formatted string to spewed to the debugger.
  1135. // ... - message arguments
  1136. //
  1137. // Return Values:
  1138. // None.
  1139. //
  1140. //--
  1141. //////////////////////////////////////////////////////////////////////////////
  1142. void
  1143. TraceMsg(
  1144. TRACEFLAG tfIn,
  1145. LPCSTR pszFormatIn,
  1146. ...
  1147. )
  1148. {
  1149. va_list valist;
  1150. if ( IsDebugFlagSet( tfIn ) )
  1151. {
  1152. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1153. LPTSTR pszBuf;
  1154. int cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1155. DebugInitializeBuffer( NULL, 0, __MODULE__, szBuf, &cchSize, &pszBuf );
  1156. #ifdef UNICODE
  1157. //
  1158. // Convert the format buffer to wide chars
  1159. //
  1160. WCHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1161. mbstowcs( szFormat, pszFormatIn, StrLenA( pszFormatIn ) + 1 );
  1162. va_start( valist, pszFormatIn );
  1163. wvnsprintf( pszBuf, cchSize, szFormat, valist );
  1164. va_end( valist );
  1165. #else
  1166. va_start( valist, pszFormatIn );
  1167. wvnsprintf( pszBuf, cchSize, pszFormatIn, valist );
  1168. va_end( valist );
  1169. #endif // UNICODE
  1170. DebugOutputString( szBuf );
  1171. } // if: flags set
  1172. } //*** TraceMsg( ) - ASCII
  1173. //////////////////////////////////////////////////////////////////////////////
  1174. //++
  1175. //
  1176. // UNICODE version
  1177. //
  1178. // void
  1179. // TraceMsg(
  1180. // TRACEFLAG tfIn,
  1181. // LPCWSTR pszFormatIn,
  1182. // ...
  1183. // )
  1184. //
  1185. // Description:
  1186. // If any of the flags in trace flags match any of the flags set in
  1187. // tfIn, the formatted string will be printed to the debugger.
  1188. //
  1189. // Arguments:
  1190. // tfIn - Flags to be checked.
  1191. // pszFormatIn - Formatted string to spewed to the debugger.
  1192. // ... - message arguments
  1193. //
  1194. // Return Values:
  1195. // None.
  1196. //
  1197. //--
  1198. //////////////////////////////////////////////////////////////////////////////
  1199. void
  1200. TraceMsg(
  1201. TRACEFLAG tfIn,
  1202. LPCWSTR pszFormatIn,
  1203. ...
  1204. )
  1205. {
  1206. va_list valist;
  1207. if ( IsDebugFlagSet( tfIn ) )
  1208. {
  1209. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1210. LPTSTR pszBuf;
  1211. int cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1212. DebugInitializeBuffer( NULL, 0, __MODULE__, szBuf, &cchSize, &pszBuf );
  1213. #ifndef UNICODE
  1214. //
  1215. // Convert the format buffer to ascii chars
  1216. //
  1217. CHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1218. wcstombs( szFormat, pszFormatIn, StrLenW( pszFormatIn ) + 1 );
  1219. va_start( valist, pszFormatIn );
  1220. wvnsprintf( pszBuf, cchSize, szFormat, valist );
  1221. va_end( valist );
  1222. #else
  1223. va_start( valist, pszFormatIn );
  1224. wvnsprintf( pszBuf, cchSize, pszFormatIn, valist );
  1225. va_end( valist );
  1226. #endif // UNICODE
  1227. DebugOutputString( szBuf );
  1228. } // if: flags set
  1229. } //*** TraceMsg( ) - UNICODE
  1230. //////////////////////////////////////////////////////////////////////////////
  1231. //++
  1232. //
  1233. // void
  1234. // TraceMessage(
  1235. // LPCTSTR pszFileIn,
  1236. // const int nLineIn,
  1237. // LPCTSTR pszModuleIn,
  1238. // TRACEFLAG tfIn,
  1239. // LPCTSTR pszFormatIn,
  1240. // ...
  1241. // )
  1242. //
  1243. // Description:
  1244. // If any of the flags in trace flags match any of the flags set in
  1245. // tfIn, the formatted string will be printed to the debugger
  1246. // along with the filename, line number and module name supplied. This is
  1247. // used by many of the debugging macros.
  1248. //
  1249. // Arguments:
  1250. // pszFileIn - Source filename.
  1251. // nLineIn - Source line number.
  1252. // pszModuleIn - Source module.
  1253. // tfIn - Flags to be checked.
  1254. // pszFormatIn - Formatted message to be printed.
  1255. // ... - message arguments
  1256. //
  1257. // Return Values:
  1258. // None.
  1259. //
  1260. //--
  1261. //////////////////////////////////////////////////////////////////////////////
  1262. void
  1263. TraceMessage(
  1264. LPCTSTR pszFileIn,
  1265. const int nLineIn,
  1266. LPCTSTR pszModuleIn,
  1267. TRACEFLAG tfIn,
  1268. LPCTSTR pszFormatIn,
  1269. ...
  1270. )
  1271. {
  1272. va_list valist;
  1273. if ( IsDebugFlagSet( tfIn ) )
  1274. {
  1275. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1276. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1277. LPTSTR psz;
  1278. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &psz );
  1279. va_start( valist, pszFormatIn );
  1280. wvnsprintf( psz, cchSize, pszFormatIn, valist );
  1281. va_end( valist );
  1282. DebugOutputString( szBuf );
  1283. } // if: flags set
  1284. } //*** TraceMessage( )
  1285. //////////////////////////////////////////////////////////////////////////////
  1286. //++
  1287. //
  1288. // void
  1289. // TraceMessageDo(
  1290. // LPCTSTR pszFileIn,
  1291. // const int nLineIn,
  1292. // LPCTSTR pszModuleIn,
  1293. // TRACEFLAG tfIn,
  1294. // LPCTSTR pszFormatIn,
  1295. // LPCTSTR pszFuncIn,
  1296. // ...
  1297. // )
  1298. //
  1299. // Description:
  1300. // Works like TraceMessage() but takes has a function argument that is
  1301. // broken into call/result in the debug spew. This is called from the
  1302. // TraceMsgDo macro.
  1303. //
  1304. // Arguments:
  1305. // pszFileIn - Source filename.
  1306. // nLineIn - Source line number.
  1307. // pszModuleIn - Source module.
  1308. // tfIn - Flags to be checked
  1309. // pszFormatIn - Formatted return value string
  1310. // pszFuncIn - The string version of the function call.
  1311. // ... - Return value from call.
  1312. //
  1313. // Return Values:
  1314. // None.
  1315. //
  1316. //--
  1317. //////////////////////////////////////////////////////////////////////////////
  1318. void
  1319. TraceMessageDo(
  1320. LPCTSTR pszFileIn,
  1321. const int nLineIn,
  1322. LPCTSTR pszModuleIn,
  1323. TRACEFLAG tfIn,
  1324. LPCTSTR pszFormatIn,
  1325. LPCTSTR pszFuncIn,
  1326. ...
  1327. )
  1328. {
  1329. va_list valist;
  1330. if ( IsDebugFlagSet( tfIn ) )
  1331. {
  1332. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1333. LPTSTR pszBuf;
  1334. int nLen;
  1335. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1336. LPCTSTR psz = pszFuncIn;
  1337. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1338. //
  1339. // Prime the buffer
  1340. //
  1341. StrCpy( pszBuf, TEXT("V ") );
  1342. pszBuf += 2;
  1343. //
  1344. // Copy the l-var part of the expression
  1345. //
  1346. while ( *psz
  1347. && *psz != TEXT('=')
  1348. )
  1349. {
  1350. *pszBuf = *psz;
  1351. psz++;
  1352. pszBuf++;
  1353. } // while:
  1354. //
  1355. // Add the " = "
  1356. //
  1357. StrCpy( pszBuf, TEXT(" = ") );
  1358. pszBuf += 3;
  1359. //
  1360. // Add the formatted result
  1361. //
  1362. va_start( valist, pszFuncIn );
  1363. nLen = wvnsprintf( pszBuf, (int)(cchDEBUG_OUTPUT_BUFFER_SIZE - 2 - (pszBuf - &szBuf[0])), pszFormatIn, valist );
  1364. va_end( valist );
  1365. if ( nLen < 0 )
  1366. {
  1367. StrCat( szBuf, TEXT("\n") );
  1368. } // if: error
  1369. else
  1370. {
  1371. pszBuf += nLen;
  1372. StrCpy( pszBuf, TEXT("\n") );
  1373. } // else: success
  1374. DebugOutputString( szBuf );
  1375. } // if: flags set
  1376. } //*** TraceMessageDo( )
  1377. //////////////////////////////////////////////////////////////////////////////
  1378. //++
  1379. //
  1380. // void
  1381. // DebugMessage(
  1382. // LPCTSTR pszFileIn,
  1383. // const int nLineIn,
  1384. // LPCTSTR pszModuleIn,
  1385. // LPCTSTR pszFormatIn,
  1386. // ...
  1387. // )
  1388. //
  1389. // Description:
  1390. // Displays a message only in CHKed/DEBUG builds. Also appends the source
  1391. // filename, linenumber and module name to the ouput.
  1392. //
  1393. // Arguments:
  1394. // pszFileIn - Source filename.
  1395. // nLineIn - Source line number.
  1396. // pszModuleIn - Source module name.
  1397. // pszFormatIn - Formatted message to be printed.
  1398. // ... - message arguments
  1399. //
  1400. // Return Values:
  1401. // None.
  1402. //
  1403. //--
  1404. //////////////////////////////////////////////////////////////////////////////
  1405. void
  1406. DebugMessage(
  1407. LPCTSTR pszFileIn,
  1408. const int nLineIn,
  1409. LPCTSTR pszModuleIn,
  1410. LPCTSTR pszFormatIn,
  1411. ...
  1412. )
  1413. {
  1414. va_list valist;
  1415. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1416. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1417. LPTSTR pszBuf;
  1418. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1419. va_start( valist, pszFormatIn );
  1420. wvnsprintf( pszBuf, cchSize, pszFormatIn, valist );
  1421. va_end( valist );
  1422. DebugOutputString( szBuf );
  1423. } //*** DebugMessage( )
  1424. //////////////////////////////////////////////////////////////////////////////
  1425. //++
  1426. //
  1427. // void
  1428. // DebugMessageDo(
  1429. // LPCTSTR pszFileIn,
  1430. // const int nLineIn,
  1431. // LPCTSTR pszModuleIn,
  1432. // LPCTSTR pszFormatIn,
  1433. // LPCTSTR pszFuncIn,
  1434. // ...
  1435. // )
  1436. //
  1437. // Description:
  1438. // Just like TraceMessageDo() except in CHKed/DEBUG version it will
  1439. // always spew. The DebugMsgDo macros uses this function.
  1440. //
  1441. // Arguments:
  1442. // pszFileIn - Source filename.
  1443. // nLineIn - Source line number.
  1444. // pszModuleIn - Source module name.
  1445. // pszFormatIn - Formatted result message.
  1446. // pszFuncIn - The string version of the function call.
  1447. // ... - The return value of the function call.
  1448. //
  1449. // Return Values:
  1450. // None.
  1451. //
  1452. //--
  1453. //////////////////////////////////////////////////////////////////////////////
  1454. void
  1455. DebugMessageDo(
  1456. LPCTSTR pszFileIn,
  1457. const int nLineIn,
  1458. LPCTSTR pszModuleIn,
  1459. LPCTSTR pszFormatIn,
  1460. LPCTSTR pszFuncIn,
  1461. ...
  1462. )
  1463. {
  1464. va_list valist;
  1465. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1466. LPTSTR pszBuf;
  1467. int nLen;
  1468. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1469. LPCTSTR psz = pszFuncIn;
  1470. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1471. //
  1472. // Prime the buffer
  1473. //
  1474. StrCpy( pszBuf, TEXT("V ") );
  1475. pszBuf += 2;
  1476. //
  1477. // Copy the l-var part of the expression
  1478. //
  1479. while ( *psz
  1480. && *psz != TEXT('=')
  1481. )
  1482. {
  1483. *pszBuf = *psz;
  1484. psz++;
  1485. pszBuf++;
  1486. } // while:
  1487. //
  1488. // Add the " = "
  1489. //
  1490. StrCpy( pszBuf, TEXT(" = ") );
  1491. pszBuf += 3;
  1492. //
  1493. // Add the formatted result
  1494. //
  1495. va_start( valist, pszFuncIn );
  1496. nLen = wvnsprintf( pszBuf, (int)(cchDEBUG_OUTPUT_BUFFER_SIZE - 2 - (pszBuf - &szBuf[ 0 ])), pszFormatIn, valist );
  1497. va_end( valist );
  1498. if ( nLen < 0 )
  1499. {
  1500. StrCat( szBuf, TEXT("\n") );
  1501. } // if: error
  1502. else
  1503. {
  1504. pszBuf += nLen;
  1505. StrCpy( pszBuf, TEXT("\n") );
  1506. } // else: success
  1507. DebugOutputString( szBuf );
  1508. } //*** DebugMessageDo( )
  1509. //////////////////////////////////////////////////////////////////////////////
  1510. //++
  1511. //
  1512. // ASCII version
  1513. //
  1514. // void
  1515. // DebugMsg(
  1516. // LPCSTR pszFormatIn,
  1517. // ...
  1518. // )
  1519. //
  1520. // Description:
  1521. // In CHKed/DEBUG version, prints a formatted message to the debugger. This
  1522. // is a NOP in REAIL version. Helpful for putting in quick debugging
  1523. // comments.
  1524. //
  1525. // Arguments:
  1526. // pszFormatIn - Formatted message to be printed.
  1527. // ... - Arguments for the message.
  1528. //
  1529. // Return Values:
  1530. // None.
  1531. //
  1532. //--
  1533. //////////////////////////////////////////////////////////////////////////////
  1534. void
  1535. DebugMsg(
  1536. LPCSTR pszFormatIn,
  1537. ...
  1538. )
  1539. {
  1540. va_list valist;
  1541. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1542. LPTSTR pszBuf;
  1543. int cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1544. DebugInitializeBuffer( NULL, 0, __MODULE__, szBuf, &cchSize, &pszBuf );
  1545. #ifdef UNICODE
  1546. //
  1547. // Convert the format buffer to wide chars
  1548. //
  1549. WCHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1550. mbstowcs( szFormat, pszFormatIn, StrLenA( pszFormatIn ) + 1 );
  1551. va_start( valist, pszFormatIn );
  1552. wvnsprintf( pszBuf, cchSize, szFormat, valist);
  1553. va_end( valist );
  1554. #else
  1555. va_start( valist, pszFormatIn );
  1556. wvnsprintf( pszBuf, cchSize, pszFormatIn, valist);
  1557. va_end( valist );
  1558. #endif // UNICODE
  1559. DebugOutputString( szBuf );
  1560. } //*** DebugMsg( ) - ASCII version
  1561. //////////////////////////////////////////////////////////////////////////////
  1562. //++
  1563. //
  1564. // UNICODE version
  1565. //
  1566. // void
  1567. // DebugMsg(
  1568. // LPCWSTR pszFormatIn,
  1569. // ...
  1570. // )
  1571. //
  1572. // Description:
  1573. // In CHKed/DEBUG version, prints a formatted message to the debugger. This
  1574. // is a NOP in REAIL version. Helpful for putting in quick debugging
  1575. // comments.
  1576. //
  1577. // Arguments:
  1578. // pszFormatIn - Formatted message to be printed.
  1579. // ... - Arguments for the message.
  1580. //
  1581. // Return Values:
  1582. // None.
  1583. //
  1584. //--
  1585. //////////////////////////////////////////////////////////////////////////////
  1586. void
  1587. DebugMsg(
  1588. LPCWSTR pszFormatIn,
  1589. ...
  1590. )
  1591. {
  1592. va_list valist;
  1593. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1594. LPTSTR pszBuf;
  1595. int cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1596. DebugInitializeBuffer( NULL, 0, __MODULE__, szBuf, &cchSize, &pszBuf );
  1597. #ifndef UNICODE
  1598. //
  1599. // Convert the format buffer to ascii chars
  1600. //
  1601. CHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1602. wcstombs( szFormat, pszFormatIn, StrLenW( pszFormatIn ) + 1 );
  1603. va_start( valist, pszFormatIn );
  1604. wvnsprintf( pszBuf, cchSize, szFormat, valist);
  1605. va_end( valist );
  1606. #else
  1607. va_start( valist, pszFormatIn );
  1608. wvnsprintf( pszBuf, cchSize, pszFormatIn, valist);
  1609. va_end( valist );
  1610. #endif // UNICODE
  1611. DebugOutputString( szBuf );
  1612. } //*** DebugMsg( ) - UNICODE version
  1613. //////////////////////////////////////////////////////////////////////////////
  1614. //++
  1615. //
  1616. // BOOL
  1617. // AssertMessage(
  1618. // LPCTSTR pszFileIn,
  1619. // const int nLineIn,
  1620. // LPCTSTR pszModuleIn,
  1621. // LPCTSTR pszfnIn,
  1622. // BOOL fTrueIn
  1623. // )
  1624. //
  1625. // Description:
  1626. // Displays a dialog box with the failed assertion. User has the option of
  1627. // breaking. The Assert macro calls this to display assertion failures.
  1628. //
  1629. // Arguments:
  1630. // pszFileIn - Source filename.
  1631. // nLineIn - Source line number.
  1632. // pszModuleIn - Source module name.
  1633. // pszfnIn - String version of the expression to assert.
  1634. // fTrueIn - Result of the evaluation of the expression.
  1635. //
  1636. // Return Values:
  1637. // TRUE - Caller should call DEBUG_BREAK.
  1638. // FALSE - Caller should not call DEBUG_BREAK.
  1639. //
  1640. //--
  1641. //////////////////////////////////////////////////////////////////////////////
  1642. BOOL
  1643. AssertMessage(
  1644. LPCTSTR pszFileIn,
  1645. const int nLineIn,
  1646. LPCTSTR pszModuleIn,
  1647. LPCTSTR pszfnIn,
  1648. BOOL fTrueIn
  1649. )
  1650. {
  1651. BOOL fTrue = fTrueIn;
  1652. if ( ! fTrueIn )
  1653. {
  1654. LRESULT lResult;
  1655. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1656. TCHAR szFileLine[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1657. LPTSTR pszBuf;
  1658. LPCTSTR pszfn = pszfnIn;
  1659. int cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1660. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1661. wnsprintf( pszBuf, cchSize, TEXT("ASSERT: %s\n"), pszfn );
  1662. //
  1663. // Dump the buffers
  1664. //
  1665. DebugOutputString( szBuf );
  1666. wnsprintf( szBuf,
  1667. cchDEBUG_OUTPUT_BUFFER_SIZE,
  1668. TEXT("Module:\t%s\t\nLine:\t%u\t\nFile:\t%s\t\n\nAssertion:\t%s\t\n\nDo you want to break here?"),
  1669. pszModuleIn,
  1670. nLineIn,
  1671. pszFileIn,
  1672. pszfn
  1673. );
  1674. lResult = MessageBox( NULL, szBuf, TEXT("Assertion Failed!"), MB_YESNO | MB_ICONWARNING );
  1675. if ( lResult == IDNO )
  1676. {
  1677. fTrue = TRUE; // don't break
  1678. } // if:
  1679. } // if: assert false
  1680. return ! fTrue;
  1681. } //*** AssertMessage( )
  1682. //////////////////////////////////////////////////////////////////////////////
  1683. //++
  1684. //
  1685. // HRESULT
  1686. // TraceHR(
  1687. // LPCTSTR pszFileIn,
  1688. // const int nLineIn,
  1689. // LPCTSTR pszModuleIn,
  1690. // LPCTSTR pszfnIn,
  1691. // HRESULT hrIn,
  1692. // BOOL fSuccessIn
  1693. // )
  1694. //
  1695. // Description:
  1696. // Traces HRESULT errors. A dialog will appear if the hrIn is not equal
  1697. // to S_OK. The dialog will ask if the user wants to break-in or continue
  1698. // execution. This is called from the THR macro.
  1699. //
  1700. // Arguments:
  1701. // pszFileIn - Source filename.
  1702. // nLineIn - Source line number.
  1703. // pszModuleIn - Source module name.
  1704. // pszfnIn - String version of the function call.
  1705. // hrIn - HRESULT of the function call.
  1706. // fSuccessIn - If TRUE, only if FAILED( hr ) is TRUE will it report.
  1707. //
  1708. // Return Values:
  1709. // Whatever hrIn is.
  1710. //
  1711. //--
  1712. //////////////////////////////////////////////////////////////////////////////
  1713. HRESULT
  1714. TraceHR(
  1715. LPCTSTR pszFileIn,
  1716. const int nLineIn,
  1717. LPCTSTR pszModuleIn,
  1718. LPCTSTR pszfnIn,
  1719. HRESULT hrIn,
  1720. BOOL fSuccessIn
  1721. )
  1722. {
  1723. if ( ( fSuccessIn
  1724. && FAILED( hrIn )
  1725. )
  1726. || ( ! fSuccessIn
  1727. && hrIn != S_OK
  1728. )
  1729. )
  1730. {
  1731. TCHAR szSymbolicName[ 64 ]; // random
  1732. DWORD cchSymbolicName;
  1733. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1734. LPTSTR pszBuf;
  1735. LPTSTR pszMsgBuf;
  1736. LRESULT lResult;
  1737. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1738. bool fAllocatedMsg = false;
  1739. switch ( hrIn )
  1740. {
  1741. case S_FALSE:
  1742. pszMsgBuf = TEXT("S_FALSE\n");
  1743. //
  1744. // Find the symbolic name for this error.
  1745. //
  1746. cchSymbolicName = sizeof( TEXT("S_FALSE") ) / sizeof( TEXT("S_FALSE") );
  1747. Assert( cchSymbolicName <= sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] ) );
  1748. StrCpy( szSymbolicName, TEXT("S_FALSE") );
  1749. break;
  1750. default:
  1751. FormatMessage(
  1752. FORMAT_MESSAGE_ALLOCATE_BUFFER
  1753. | FORMAT_MESSAGE_FROM_SYSTEM,
  1754. NULL,
  1755. hrIn,
  1756. MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  1757. (LPTSTR) &pszMsgBuf,
  1758. 0,
  1759. NULL
  1760. );
  1761. //
  1762. // Make sure everything is cool before we blow up somewhere else.
  1763. //
  1764. if ( pszMsgBuf == NULL )
  1765. {
  1766. pszMsgBuf = TEXT("<unknown error code returned>\n");
  1767. } // if: status code not found
  1768. else
  1769. {
  1770. fAllocatedMsg = true;
  1771. } // else: found the status code
  1772. //
  1773. // Find the symbolic name for this error.
  1774. //
  1775. cchSymbolicName = sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] );
  1776. DebugFindWinerrorSymbolicName( hrIn, szSymbolicName, &cchSymbolicName );
  1777. Assert( cchSymbolicName != sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] ) );
  1778. break;
  1779. } // switch: hrIn
  1780. Assert( pszFileIn != NULL );
  1781. Assert( pszModuleIn != NULL );
  1782. Assert( pszfnIn != NULL );
  1783. //
  1784. // Spew it to the debugger.
  1785. //
  1786. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1787. wnsprintf( pszBuf,
  1788. cchSize,
  1789. TEXT("*HRESULT* hr = 0x%08x (%s) - %s"),
  1790. hrIn,
  1791. szSymbolicName,
  1792. pszMsgBuf
  1793. );
  1794. DebugOutputString( szBuf );
  1795. //
  1796. // If trace flag set, generate a pop-up.
  1797. //
  1798. if ( IsTraceFlagSet( mtfASSERT_HR ) )
  1799. {
  1800. wnsprintf( szBuf,
  1801. cchDEBUG_OUTPUT_BUFFER_SIZE,
  1802. TEXT("Module:\t%s\t\nLine:\t%u\t\nFile:\t%s\t\n\nFunction:\t%s\t\nhr =\t0x%08x (%s) - %s\t\nDo you want to break here?"),
  1803. pszModuleIn,
  1804. nLineIn,
  1805. pszFileIn,
  1806. pszfnIn,
  1807. hrIn,
  1808. szSymbolicName,
  1809. pszMsgBuf
  1810. );
  1811. lResult = MessageBox( NULL, szBuf, TEXT("Trace HRESULT"), MB_YESNO | MB_ICONWARNING );
  1812. if ( lResult == IDYES )
  1813. {
  1814. DEBUG_BREAK;
  1815. } // if: break
  1816. } // if: asserting on non-success HRESULTs
  1817. if ( fAllocatedMsg )
  1818. {
  1819. LocalFree( pszMsgBuf );
  1820. } // if: message buffer was allocated by FormateMessage( )
  1821. } // if: hrIn != S_OK
  1822. return hrIn;
  1823. } //*** TraceHR( )
  1824. //////////////////////////////////////////////////////////////////////////////
  1825. //++
  1826. //
  1827. // ULONG
  1828. // TraceWin32(
  1829. // LPCTSTR pszFileIn,
  1830. // const int nLineIn,
  1831. // LPCTSTR pszModuleIn,
  1832. // LPCTSTR pszfnIn,
  1833. // ULONG ulErrIn
  1834. // )
  1835. //
  1836. // Description:
  1837. // Traces WIN32 errors. A dialog will appear is the ulErrIn is not equal
  1838. // to ERROR_SUCCESS. The dialog will ask if the user wants to break-in or
  1839. // continue execution.
  1840. //
  1841. // Arguments:
  1842. // pszFileIn - Source filename.
  1843. // nLineIn - Source line number.
  1844. // pszModuleIn - Source module name.
  1845. // pszfnIn - String version of the function call.
  1846. // ulErrIn - Error code to check.
  1847. //
  1848. // Return Values:
  1849. // Whatever ulErrIn is.
  1850. //
  1851. //--
  1852. //////////////////////////////////////////////////////////////////////////////
  1853. ULONG
  1854. TraceWin32(
  1855. LPCTSTR pszFileIn,
  1856. const int nLineIn,
  1857. LPCTSTR pszModuleIn,
  1858. LPCTSTR pszfnIn,
  1859. ULONG ulErrIn
  1860. )
  1861. {
  1862. if ( ulErrIn != ERROR_SUCCESS )
  1863. {
  1864. TCHAR szSymbolicName[ 64 ]; // random
  1865. DWORD cchSymbolicName;
  1866. TCHAR szBuf[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  1867. LPTSTR pszBuf;
  1868. LPTSTR pszMsgBuf;
  1869. LRESULT lResult;
  1870. INT cchSize = cchDEBUG_OUTPUT_BUFFER_SIZE;
  1871. bool fAllocatedMsg = false;
  1872. FormatMessage(
  1873. FORMAT_MESSAGE_ALLOCATE_BUFFER
  1874. | FORMAT_MESSAGE_FROM_SYSTEM,
  1875. NULL,
  1876. ulErrIn,
  1877. MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  1878. (LPTSTR) &pszMsgBuf,
  1879. 0,
  1880. NULL
  1881. );
  1882. //
  1883. // Make sure everything is cool before we blow up somewhere else.
  1884. //
  1885. if ( pszMsgBuf == NULL )
  1886. {
  1887. pszMsgBuf = TEXT("<unknown error code returned>\n");
  1888. } // if: status code not found
  1889. else
  1890. {
  1891. fAllocatedMsg = true;
  1892. } // else: found the status code
  1893. Assert( pszFileIn != NULL );
  1894. Assert( pszModuleIn != NULL );
  1895. Assert( pszfnIn != NULL );
  1896. //
  1897. // Find the symbolic name for this error.
  1898. //
  1899. cchSymbolicName = sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] );
  1900. DebugFindWinerrorSymbolicName( ulErrIn, szSymbolicName, &cchSymbolicName );
  1901. Assert( cchSymbolicName != sizeof( szSymbolicName ) / sizeof( szSymbolicName[ 0 ] ) );
  1902. //
  1903. // Spew it to the debugger.
  1904. //
  1905. DebugInitializeBuffer( pszFileIn, nLineIn, pszModuleIn, szBuf, &cchSize, &pszBuf );
  1906. wnsprintf( pszBuf,
  1907. cchSize,
  1908. TEXT("*WIN32Err* ulErr = %u (%s) - %s"),
  1909. ulErrIn,
  1910. szSymbolicName,
  1911. pszMsgBuf
  1912. );
  1913. DebugOutputString( szBuf );
  1914. //
  1915. // If trace flag set, invoke a pop-up.
  1916. //
  1917. if ( IsTraceFlagSet( mtfASSERT_HR ) )
  1918. {
  1919. wnsprintf( szBuf,
  1920. cchDEBUG_OUTPUT_BUFFER_SIZE,
  1921. TEXT("Module:\t%s\t\nLine:\t%u\t\nFile:\t%s\t\n\nFunction:\t%s\t\nulErr =\t%u (%s) - %s\t\nDo you want to break here?"),
  1922. pszModuleIn,
  1923. nLineIn,
  1924. pszFileIn,
  1925. pszfnIn,
  1926. ulErrIn,
  1927. szSymbolicName,
  1928. pszMsgBuf
  1929. );
  1930. lResult = MessageBox( NULL, szBuf, TEXT("Trace Win32"), MB_YESNO | MB_ICONWARNING );
  1931. if ( lResult == IDYES )
  1932. {
  1933. DEBUG_BREAK;
  1934. } // if: break
  1935. } // if: asserting on non-success status codes
  1936. if ( fAllocatedMsg )
  1937. {
  1938. LocalFree( pszMsgBuf );
  1939. } // if: message buffer was allocated by FormateMessage( )
  1940. } // if: ulErrIn != ERROR_SUCCESS
  1941. return ulErrIn;
  1942. } //*** TraceWin32( )
  1943. //****************************************************************************
  1944. //****************************************************************************
  1945. //
  1946. // Memory allocation and tracking
  1947. //
  1948. //****************************************************************************
  1949. //****************************************************************************
  1950. //
  1951. // This is a private structure and should not be known to the application.
  1952. //
  1953. typedef struct MEMORYBLOCK
  1954. {
  1955. EMEMORYBLOCKTYPE mbtType; // What type of memory this is tracking
  1956. union
  1957. {
  1958. HGLOBAL hGlobal; // handle/pointer/object to allocated memory to track
  1959. BSTR bstr; // BSTR to allocated memory
  1960. };
  1961. DWORD dwBytes; // size of the memory
  1962. UINT uFlags; // flags used to allocate memory
  1963. LPCTSTR pszFile; // source filename where memory was allocated
  1964. int nLine; // source line number where memory was allocated
  1965. LPCTSTR pszModule; // source module name where memory was allocated
  1966. LPCTSTR pszComment; // optional comments about the memory
  1967. MEMORYBLOCK * pNext; // pointer to next MEMORYBLOCK structure
  1968. } MEMORYBLOCK;
  1969. typedef struct MEMORYBLOCKLIST
  1970. {
  1971. LONG lSpinLock; // Spin lock protecting the list
  1972. MEMORYBLOCK * pmbList; // List of MEMORYBLOCKs.
  1973. BOOL fDeadList; // The list is dead.
  1974. } MEMORYBLOCKLIST;
  1975. //////////////////////////////////////////////////////////////////////////////
  1976. //++
  1977. //
  1978. // void
  1979. // DebugMemorySpew(
  1980. // MEMORYBLOCK * pmb,
  1981. // LPTSTR pszMessage
  1982. // )
  1983. //
  1984. // Description:
  1985. // Displays a message about the memory block.
  1986. //
  1987. // Arugments:
  1988. // pmb - pointer to MEMORYBLOCK desciptor.
  1989. // pszMessage - message to display
  1990. //
  1991. // Return Values:
  1992. // None.
  1993. //
  1994. //--
  1995. //////////////////////////////////////////////////////////////////////////////
  1996. void
  1997. DebugMemorySpew(
  1998. MEMORYBLOCK * pmb,
  1999. LPTSTR pszMessage
  2000. )
  2001. {
  2002. switch ( pmb->mbtType )
  2003. {
  2004. case mmbtMEMORYALLOCATION:
  2005. DebugMessage( pmb->pszFile,
  2006. pmb->nLine,
  2007. pmb->pszModule,
  2008. TEXT("%s %s - %u bytes at 0x%08x\n"),
  2009. pszMessage,
  2010. pmb->pszComment,
  2011. pmb->dwBytes,
  2012. pmb->hGlobal
  2013. );
  2014. break;
  2015. case mmbtOBJECT:
  2016. case mmbtPUNK:
  2017. case mmbtHANDLE:
  2018. DebugMessage( pmb->pszFile,
  2019. pmb->nLine,
  2020. pmb->pszModule,
  2021. TEXT("%s %s = 0x%08x\n"),
  2022. pszMessage,
  2023. pmb->pszComment,
  2024. pmb->hGlobal
  2025. );
  2026. break;
  2027. } // switch: pmb->mbtType
  2028. } //*** DebugMemorySpew( )
  2029. //////////////////////////////////////////////////////////////////////////////
  2030. //++
  2031. //
  2032. // HGLOBAL
  2033. // DebugMemoryAdd(
  2034. // EMEMORYBLOCKTYPE mbtType,
  2035. // HGLOBAL hGlobalIn,
  2036. // LPCTSTR pszFileIn,
  2037. // const int nLineIn,
  2038. // LPCTSTR pszModuleIn,
  2039. // UINT uFlagsIn,
  2040. // DWORD dwBytesIn,
  2041. // LPCTSTR pszCommentIn
  2042. // )
  2043. //
  2044. // Description:
  2045. // Adds memory to be tracked to the memory tracking list.
  2046. //
  2047. // Arguments:
  2048. // mbtType - Type of memory block of the memory to track.
  2049. // hGlobalIn - Handle/pointer to memory to track.
  2050. // pszFileIn - Source filename where memory was allocated.
  2051. // nLineIn - Source line number where memory was allocated.
  2052. // pszModuleIn - Source module where memory was allocated.
  2053. // uFlagsIn - Flags used to allocate the memory.
  2054. // dwBytesIn - Size of the allocation.
  2055. // pszCommentIn - Optional comments about the memory.
  2056. //
  2057. // Return Values:
  2058. // Whatever was in hGlobalIn.
  2059. //
  2060. //--
  2061. //////////////////////////////////////////////////////////////////////////////
  2062. HGLOBAL
  2063. DebugMemoryAdd(
  2064. EMEMORYBLOCKTYPE mbtType,
  2065. HGLOBAL hGlobalIn,
  2066. LPCTSTR pszFileIn,
  2067. const int nLineIn,
  2068. LPCTSTR pszModuleIn,
  2069. UINT uFlagsIn,
  2070. DWORD dwBytesIn,
  2071. LPCTSTR pszCommentIn
  2072. )
  2073. {
  2074. if ( hGlobalIn != NULL )
  2075. {
  2076. MEMORYBLOCK * pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2077. MEMORYBLOCK * pmb = (MEMORYBLOCK *) GlobalAlloc( GMEM_FIXED, sizeof( MEMORYBLOCK ) );
  2078. if ( pmb == NULL )
  2079. {
  2080. GlobalFree( hGlobalIn );
  2081. return NULL;
  2082. } // if: memory block allocation failed
  2083. pmb->mbtType = mbtType;
  2084. pmb->hGlobal = hGlobalIn;
  2085. pmb->dwBytes = dwBytesIn;
  2086. pmb->uFlags = uFlagsIn;
  2087. pmb->pszFile = pszFileIn;
  2088. pmb->nLine = nLineIn;
  2089. pmb->pszModule = pszModuleIn;
  2090. pmb->pszComment = pszCommentIn;
  2091. pmb->pNext = pmbHead;
  2092. TlsSetValue( g_TraceMemoryIndex, pmb );
  2093. //
  2094. // Spew if needed
  2095. //
  2096. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  2097. {
  2098. DebugMemorySpew( pmb, TEXT("Alloced") );
  2099. } // if: tracing
  2100. } // if: something to trace
  2101. return hGlobalIn;
  2102. } //*** DebugMemoryAdd( )
  2103. //////////////////////////////////////////////////////////////////////////////
  2104. //++
  2105. //
  2106. // void
  2107. // DebugMemoryDelete(
  2108. // EMEMORYBLOCKTYPE mbtTypeIn,
  2109. // HGLOBAL hGlobalIn
  2110. // LPCTSTR pszFileIn,
  2111. // const int nLineIn,
  2112. // LPCTSTR pszModuleIn,
  2113. // BOOL fClobberIn
  2114. // )
  2115. //
  2116. // Description:
  2117. // Removes a MEMORYBLOCK to the memory tracking list.
  2118. //
  2119. // Arguments:
  2120. // mbtTypeIn - Memory block type.
  2121. // hGlobalIn - Handle/pointer to memory block to stop tracking.
  2122. // pszFileIn - Source file that is deleteing.
  2123. // nLineIn - Source line number that is deleteing.
  2124. // pszModuleIn - Source module name that is deleteing.
  2125. // fClobberIn - True is memory should be scrambled.
  2126. //
  2127. // Return Values:
  2128. // None.
  2129. //
  2130. //--
  2131. //////////////////////////////////////////////////////////////////////////////
  2132. void
  2133. DebugMemoryDelete(
  2134. EMEMORYBLOCKTYPE mbtTypeIn,
  2135. HGLOBAL hGlobalIn,
  2136. LPCTSTR pszFileIn,
  2137. const int nLineIn,
  2138. LPCTSTR pszModuleIn,
  2139. BOOL fClobberIn
  2140. )
  2141. {
  2142. if ( hGlobalIn != NULL )
  2143. {
  2144. MEMORYBLOCK * pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2145. MEMORYBLOCK * pmbLast = NULL;
  2146. //
  2147. // Find the memory in the memory block list
  2148. //
  2149. if ( mbtTypeIn == mmbtMEMORYALLOCATION )
  2150. {
  2151. while ( pmbHead != NULL
  2152. && !( pmbHead->hGlobal == hGlobalIn
  2153. && pmbHead->mbtType == mbtTypeIn
  2154. )
  2155. )
  2156. {
  2157. AssertMsg( !( pmbHead->hGlobal == hGlobalIn && pmbHead->mbtType == mmbtSYSALLOCSTRING ),
  2158. "Should be freed by SysAllocFreeString( )." );
  2159. pmbLast = pmbHead;
  2160. pmbHead = pmbLast->pNext;
  2161. } // while: finding the entry in the list
  2162. } // if: memory allocation type
  2163. else if ( mbtTypeIn == mmbtSYSALLOCSTRING )
  2164. {
  2165. while ( pmbHead != NULL
  2166. && !( pmbHead->hGlobal == hGlobalIn
  2167. && pmbHead->mbtType == mbtTypeIn
  2168. )
  2169. )
  2170. {
  2171. AssertMsg( !( pmbHead->hGlobal == hGlobalIn && pmbHead->mbtType == mmbtMEMORYALLOCATION ),
  2172. "Should be freed by TraceFree( )." );
  2173. pmbLast = pmbHead;
  2174. pmbHead = pmbLast->pNext;
  2175. } // while: finding the entry in the list
  2176. } // if: SysAllocString type
  2177. else if ( mbtTypeIn == mmbtUNKNOWN )
  2178. {
  2179. while ( pmbHead != NULL
  2180. && pmbHead->hGlobal != hGlobalIn
  2181. )
  2182. {
  2183. pmbLast = pmbHead;
  2184. pmbHead = pmbLast->pNext;
  2185. } // while: finding the entry in the list
  2186. } // if: don't care what type
  2187. else
  2188. {
  2189. while ( pmbHead != NULL
  2190. && !( pmbHead->hGlobal == hGlobalIn
  2191. && pmbHead->mbtType == mbtTypeIn
  2192. )
  2193. )
  2194. {
  2195. pmbLast = pmbHead;
  2196. pmbHead = pmbLast->pNext;
  2197. } // while: finding the entry in the list
  2198. } // else: other types, but they must match
  2199. if ( pmbHead != NULL )
  2200. {
  2201. //
  2202. // Remove the memory block from the tracking list
  2203. //
  2204. if ( pmbLast != NULL )
  2205. {
  2206. pmbLast->pNext = pmbHead->pNext;
  2207. } // if: not first entry
  2208. else
  2209. {
  2210. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  2211. } // else: first entry
  2212. //
  2213. // Spew if needed
  2214. //
  2215. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  2216. {
  2217. DebugMemorySpew( pmbHead, TEXT("Freeing") );
  2218. } // if: tracing
  2219. //
  2220. // Nuke the memory
  2221. //
  2222. if ( fClobberIn
  2223. && pmbHead->mbtType == mmbtMEMORYALLOCATION
  2224. )
  2225. {
  2226. if ( pmbHead->uFlags & GMEM_MOVEABLE )
  2227. {
  2228. LPVOID pv = GlobalLock( pmbHead->hGlobal );
  2229. memset( pv, 0xFA, pmbHead->dwBytes );
  2230. GlobalUnlock( pmbHead->hGlobal );
  2231. } // if: moveable memory
  2232. else
  2233. {
  2234. Assert( pmbHead->uFlags == 0 || pmbHead->uFlags == LPTR || pmbHead->dwBytes == 0 );
  2235. memset( pmbHead->hGlobal, 0xFA, pmbHead->dwBytes );
  2236. } // else: fixed memory
  2237. } // if: block is memory alloction
  2238. //
  2239. // Nuke the memory tracking block
  2240. //
  2241. memset( pmbHead, 0xFB, sizeof( MEMORYBLOCK ) );
  2242. GlobalFree( pmbHead );
  2243. } // if: found entry
  2244. else
  2245. {
  2246. DebugMessage( pszFileIn,
  2247. nLineIn,
  2248. pszModuleIn,
  2249. TEXT("***** Attempted to free 0x%08x not owned by thread (ThreadID = 0x%08x) *****\n"),
  2250. hGlobalIn,
  2251. GetCurrentThreadId( )
  2252. );
  2253. } // else: entry not found
  2254. } // if: something to delete
  2255. } //*** DebugMemoryDelete( )
  2256. //////////////////////////////////////////////////////////////////////////////
  2257. //++
  2258. //
  2259. // HGLOBAL
  2260. // DebugAlloc(
  2261. // LPCTSTR pszFileIn,
  2262. // const int nLineIn,
  2263. // LPCTSTR pszModuleIn,
  2264. // UINT uFlagsIn,
  2265. // DWORD dwBytesIn,
  2266. // LPCTSTR pszCommentIn
  2267. // )
  2268. //
  2269. // Description:
  2270. // Replacement for Local/GlobalAlloc for CHKed/DEBUG builds. Memory
  2271. // allocations be tracked. Use the TraceAlloc macro to make memory
  2272. // allocations switch in RETAIL.
  2273. //
  2274. // Arguments:
  2275. // pszFileIn - Source filename where memory was allocated.
  2276. // nLineIn - Source line number where memory was allocated.
  2277. // pszModuleIn - Source module where memory was allocated.
  2278. // uFlagsIn - Flags used to allocate the memory.
  2279. // dwBytesIn - Size of the allocation.
  2280. // pszCommentIn - Optional comments about the memory.
  2281. //
  2282. // Return Values:
  2283. // Handle/pointer to the new allocation. NULL is allocation failed.
  2284. //
  2285. //--
  2286. //////////////////////////////////////////////////////////////////////////////
  2287. HGLOBAL
  2288. DebugAlloc(
  2289. LPCTSTR pszFileIn,
  2290. const int nLineIn,
  2291. LPCTSTR pszModuleIn,
  2292. UINT uFlagsIn,
  2293. DWORD dwBytesIn,
  2294. LPCTSTR pszCommentIn
  2295. )
  2296. {
  2297. HGLOBAL hGlobal = GlobalAlloc( uFlagsIn, dwBytesIn );
  2298. //
  2299. // Initialize the memory if needed
  2300. //
  2301. if ( IsTraceFlagSet( mtfMEMORYINIT )
  2302. && !( uFlagsIn & GMEM_ZEROINIT )
  2303. )
  2304. {
  2305. if ( uFlagsIn & GMEM_MOVEABLE )
  2306. {
  2307. LPVOID pv = GlobalLock( hGlobal );
  2308. if ( pv != NULL )
  2309. {
  2310. memset( pv, 0xAA, dwBytesIn );
  2311. GlobalUnlock( hGlobal );
  2312. } // if: lock granted
  2313. } // if: moveable block
  2314. else
  2315. {
  2316. //
  2317. // KB: gpease 8-NOV-1999
  2318. // Initialize to anything but ZERO. We will use 0xAA to
  2319. // indicate "Available Address". Initializing to zero
  2320. // is bad because it usually has meaning.
  2321. //
  2322. memset( hGlobal, 0xAA, dwBytesIn );
  2323. } // else: fixed block
  2324. } // if: zero memory requested
  2325. return DebugMemoryAdd( mmbtMEMORYALLOCATION,
  2326. hGlobal,
  2327. pszFileIn,
  2328. nLineIn,
  2329. pszModuleIn,
  2330. uFlagsIn,
  2331. dwBytesIn,
  2332. pszCommentIn
  2333. );
  2334. } //*** DebugAlloc( )
  2335. //////////////////////////////////////////////////////////////////////////////
  2336. //++
  2337. //
  2338. // HGLOBAL
  2339. // DebugReAlloc(
  2340. // LPCTSTR pszFileIn,
  2341. // const int nLineIn,
  2342. // LPCTSTR pszModuleIn,
  2343. // HGLOBAL hMemIn,
  2344. // UINT uFlagsIn,
  2345. // DWORD dwBytesIn,
  2346. // LPCTSTR pszCommentIn
  2347. // )
  2348. //
  2349. // Description:
  2350. // Replacement for Local/GlobalAlloc for CHKed/DEBUG builds. Memory
  2351. // allocations be tracked. Use the TraceAlloc macro to make memory
  2352. // allocations switch in RETAIL.
  2353. //
  2354. // Arguments:
  2355. // pszFileIn - Source filename where memory was allocated.
  2356. // nLineIn - Source line number where memory was allocated.
  2357. // pszModuleIn - Source module where memory was allocated.
  2358. // uFlagsIn - Flags used to allocate the memory.
  2359. // dwBytesIn - Size of the allocation.
  2360. // pszCommentIn - Optional comments about the memory.
  2361. //
  2362. // Return Values:
  2363. // Handle/pointer to the new allocation.
  2364. // NULL if allocation failed.
  2365. //
  2366. //--
  2367. //////////////////////////////////////////////////////////////////////////////
  2368. HGLOBAL
  2369. DebugReAlloc(
  2370. LPCTSTR pszFileIn,
  2371. const int nLineIn,
  2372. LPCTSTR pszModuleIn,
  2373. HGLOBAL hMemIn,
  2374. UINT uFlagsIn,
  2375. DWORD dwBytesIn,
  2376. LPCTSTR pszCommentIn
  2377. )
  2378. {
  2379. MEMORYBLOCK * pmbHead = NULL;
  2380. HGLOBAL hGlobalOld = hMemIn;
  2381. HGLOBAL hGlobal;
  2382. AssertMsg( !( uFlagsIn & GMEM_MODIFY ), "This doesn't handle modified memory blocks, yet." );
  2383. if ( hMemIn != NULL )
  2384. {
  2385. MEMORYBLOCK * pmbLast = NULL;
  2386. pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2387. //
  2388. // Find the memory in the memory block list
  2389. //
  2390. while ( pmbHead != NULL
  2391. && pmbHead->hGlobal != hMemIn
  2392. )
  2393. {
  2394. pmbLast = pmbHead;
  2395. pmbHead = pmbLast->pNext;
  2396. } // while: finding the entry in the list
  2397. if ( pmbHead != NULL )
  2398. {
  2399. AssertMsg( pmbHead->mbtType == mmbtMEMORYALLOCATION, "You can only realloc memory allocations!" );
  2400. //
  2401. // Remove the memory from the tracking list
  2402. //
  2403. if ( pmbLast != NULL )
  2404. {
  2405. pmbLast->pNext = pmbHead->pNext;
  2406. } // if: not first entry
  2407. else
  2408. {
  2409. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  2410. } // else: first entry
  2411. //
  2412. // Spew if needed
  2413. //
  2414. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  2415. {
  2416. DebugMemorySpew( pmbHead, TEXT("Freeing") );
  2417. } // if: tracing
  2418. //
  2419. // Force the programmer to handle a real realloc by moving the
  2420. // memory first.
  2421. //
  2422. hGlobalOld = GlobalAlloc( pmbHead->uFlags, pmbHead->dwBytes );
  2423. if ( hGlobalOld != NULL )
  2424. {
  2425. if ( pmbHead->uFlags & GMEM_MOVEABLE
  2426. )
  2427. {
  2428. LPVOID pvDest = GlobalLock( hGlobalOld );
  2429. LPVOID pvSrc = GlobalLock( hMemIn );
  2430. CopyMemory( pvDest, pvSrc, pmbHead->dwBytes );
  2431. //
  2432. // Nuke the old memory if the allocation is to be smaller.
  2433. //
  2434. if ( dwBytesIn < pmbHead->dwBytes )
  2435. {
  2436. LPBYTE pb = (LPBYTE) pvDest + dwBytesIn;
  2437. memset( pb, 0xFA, pmbHead->dwBytes - dwBytesIn );
  2438. } // if: smaller memory
  2439. GlobalUnlock( hMemIn );
  2440. GlobalUnlock( hGlobalOld );
  2441. } // if: moveable memory
  2442. else
  2443. {
  2444. CopyMemory( hGlobalOld, hMemIn, pmbHead->dwBytes );
  2445. //
  2446. // Nuke the old memory if the allocation is to be smaller.
  2447. //
  2448. if ( dwBytesIn < pmbHead->dwBytes )
  2449. {
  2450. LPBYTE pb = (LPBYTE) hGlobalOld + dwBytesIn;
  2451. memset( pb, 0xFA, pmbHead->dwBytes - dwBytesIn );
  2452. } // if: smaller memory
  2453. } // else: fixed memory
  2454. pmbHead->hGlobal = hGlobalOld;
  2455. } // if: got new memory
  2456. else
  2457. {
  2458. hGlobalOld = hMemIn;
  2459. } // else: allocation failed
  2460. } // if: found entry
  2461. else
  2462. {
  2463. DebugMessage( pszFileIn,
  2464. nLineIn,
  2465. pszModuleIn,
  2466. TEXT("***** Attempted to realloc 0x%08x not owned by thread (ThreadID = 0x%08x) *****\n"),
  2467. hMemIn,
  2468. GetCurrentThreadId( )
  2469. );
  2470. } // else: entry not found
  2471. } // if: something to delete
  2472. //
  2473. // We do this any way because the flags and input still need to be
  2474. // verified by GlobalReAlloc( ).
  2475. //
  2476. hGlobal = GlobalReAlloc( hGlobalOld, dwBytesIn, uFlagsIn );
  2477. if ( hGlobal == NULL )
  2478. {
  2479. DWORD dwErr = GetLastError( );
  2480. AssertMsg( dwErr == 0, "GlobalReAlloc() failed!" );
  2481. if ( hMemIn != hGlobalOld )
  2482. {
  2483. GlobalFree( hGlobalOld );
  2484. } // if: forced a move
  2485. SetLastError( dwErr );
  2486. if ( pmbHead != NULL )
  2487. {
  2488. //
  2489. // Continue tracking the memory by re-adding it to the tracking list.
  2490. //
  2491. pmbHead->hGlobal = hMemIn;
  2492. pmbHead->pNext = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2493. TlsSetValue( g_TraceMemoryIndex, (LPVOID) pmbHead );
  2494. } // if: reuse the old entry
  2495. else
  2496. {
  2497. //
  2498. // Create a new block
  2499. //
  2500. DebugMemoryAdd( mmbtMEMORYALLOCATION,
  2501. hGlobalOld,
  2502. pszFileIn,
  2503. nLineIn,
  2504. pszModuleIn,
  2505. uFlagsIn,
  2506. dwBytesIn,
  2507. pszCommentIn
  2508. );
  2509. } // else: make new entry
  2510. } // if: allocation failed
  2511. else
  2512. {
  2513. if ( hGlobal != hMemIn )
  2514. {
  2515. if ( pmbHead != NULL )
  2516. {
  2517. //
  2518. // Nuke the old memory
  2519. //
  2520. if ( pmbHead->uFlags & GMEM_MOVEABLE )
  2521. {
  2522. LPVOID pv = GlobalLock( hMemIn );
  2523. memset( pv, 0xFA, pmbHead->dwBytes );
  2524. GlobalUnlock( hMemIn );
  2525. } // if: moveable memory
  2526. else
  2527. {
  2528. memset( hMemIn, 0xFA, pmbHead->dwBytes );
  2529. } // else: fixed memory
  2530. } // if: entry found
  2531. //
  2532. // Free the old memory
  2533. //
  2534. GlobalFree( hMemIn );
  2535. } // if: new memory location
  2536. //
  2537. // Add the allocation to the tracking table.
  2538. //
  2539. if ( pmbHead != NULL )
  2540. {
  2541. //
  2542. // If the block is bigger, initialize the "new" memory
  2543. //
  2544. if ( IsTraceFlagSet( mtfMEMORYINIT )
  2545. && dwBytesIn > pmbHead->dwBytes
  2546. )
  2547. {
  2548. //
  2549. // Initialize the expaned memory block
  2550. //
  2551. if ( pmbHead->uFlags & GMEM_MOVEABLE )
  2552. {
  2553. LPBYTE pb = (LPBYTE) GlobalLock( hGlobal );
  2554. memset( pb + pmbHead->dwBytes, 0xAA, dwBytesIn - pmbHead->dwBytes );
  2555. GlobalUnlock( hGlobal );
  2556. } // if: moveable memory
  2557. else
  2558. {
  2559. LPBYTE pb = (LPBYTE) hGlobal + pmbHead->dwBytes;
  2560. memset( pb, 0xAA, dwBytesIn - pmbHead->dwBytes );
  2561. } // else: fixed memory
  2562. } // if: initialize memory
  2563. //
  2564. // Re-add the tracking block by reusing the old tracking block
  2565. //
  2566. pmbHead->hGlobal = hGlobal;
  2567. pmbHead->dwBytes = dwBytesIn;
  2568. pmbHead->uFlags = uFlagsIn;
  2569. pmbHead->pszFile = pszFileIn;
  2570. pmbHead->nLine = nLineIn;
  2571. pmbHead->pszModule = pszModuleIn;
  2572. pmbHead->pszComment = pszCommentIn;
  2573. pmbHead->pNext = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2574. TlsSetValue( g_TraceMemoryIndex, (LPVOID) pmbHead );
  2575. //
  2576. // Spew if needed
  2577. //
  2578. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  2579. {
  2580. DebugMemorySpew( pmbHead, TEXT("ReAlloced") );
  2581. } // if: tracing
  2582. } // if: entry found
  2583. else
  2584. {
  2585. //
  2586. // Create a new block
  2587. //
  2588. DebugMemoryAdd( mmbtMEMORYALLOCATION,
  2589. hGlobalOld,
  2590. pszFileIn,
  2591. nLineIn,
  2592. pszModuleIn,
  2593. uFlagsIn,
  2594. dwBytesIn,
  2595. pszCommentIn
  2596. );
  2597. } // else: make new entry
  2598. } // else: allocation succeeded
  2599. return hGlobal;
  2600. } //*** DebugRealloc( )
  2601. //////////////////////////////////////////////////////////////////////////////
  2602. //++
  2603. //
  2604. // HGLOBAL
  2605. // DebugFree(
  2606. // HGLOBAL hGlobalIn
  2607. // LPCTSTR pszFileIn,
  2608. // const int nLineIn,
  2609. // LPCTSTR pszModuleIn,
  2610. // )
  2611. //
  2612. // Description:
  2613. // Replacement for Local/GlobalFree for CHKed/DEBUG builds. Removes the
  2614. // memory allocation for the memory tracking list. Use the TraceFree
  2615. // macro to make memory allocation switch in RETAIL. The memory of the
  2616. // freed block will be set to 0xFE.
  2617. //
  2618. // Arguments:
  2619. // hGlobalIn - Handle/pointer to memory block to free.
  2620. // pszFileIn - Source file path to the caller
  2621. // nLineIn - Line number of the caller in the source file
  2622. // pszModuleIn - Source module name of the caller
  2623. //
  2624. // Return Values: (see GlobalFree())
  2625. // NULL if success.
  2626. // Otherwise it is equal to hGlobalIn.
  2627. //
  2628. //--
  2629. //////////////////////////////////////////////////////////////////////////////
  2630. HGLOBAL
  2631. DebugFree(
  2632. HGLOBAL hGlobalIn,
  2633. LPCTSTR pszFileIn,
  2634. const int nLineIn,
  2635. LPCTSTR pszModuleIn
  2636. )
  2637. {
  2638. DebugMemoryDelete( mmbtMEMORYALLOCATION, hGlobalIn, pszFileIn, nLineIn, pszModuleIn, TRUE );
  2639. return GlobalFree( hGlobalIn );
  2640. } //*** DebugFree( )
  2641. //////////////////////////////////////////////////////////////////////////////
  2642. //++
  2643. //
  2644. // void
  2645. // DebugMemoryCheck(
  2646. // LPVOID pvListIn,
  2647. // LPCTSTR pszListNameIn
  2648. // )
  2649. //
  2650. // Description:
  2651. // Called just before a thread/process dies to verify that all the memory
  2652. // allocated by the thread/process was properly freed. Anything that was
  2653. // not freed will be listed in the debugger.
  2654. //
  2655. // If pmbListIn is NULL, it will check the current threads tracking list.
  2656. // The list is destroyed as it is checked.
  2657. //
  2658. // Arguments:
  2659. // pvListIn - The list to check.
  2660. // pszListNameIn - The name of the list.
  2661. //
  2662. // Return Values:
  2663. // None.
  2664. //
  2665. //--
  2666. //////////////////////////////////////////////////////////////////////////////
  2667. void
  2668. DebugMemoryCheck(
  2669. LPVOID pvListIn,
  2670. LPCTSTR pszListNameIn
  2671. )
  2672. {
  2673. BOOL fFoundLeak = FALSE;
  2674. MEMORYBLOCK * pmb;
  2675. //
  2676. // Determine which list to use.
  2677. //
  2678. if ( pvListIn == NULL )
  2679. {
  2680. pmb = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2681. } // if: use the thread list
  2682. else
  2683. {
  2684. MEMORYBLOCKLIST * pmbl = (MEMORYBLOCKLIST *) pvListIn;
  2685. Assert( pszListNameIn != NULL );
  2686. //
  2687. // Make sure nobody tries to use the list again.
  2688. //
  2689. DebugAcquireSpinLock( &pmbl->lSpinLock );
  2690. pmbl->fDeadList = TRUE;
  2691. DebugReleaseSpinLock( &pmbl->lSpinLock );
  2692. pmb = pmbl->pmbList;
  2693. } // else: use the given list
  2694. //
  2695. // Print banner if needed.
  2696. //
  2697. if ( pmb != NULL )
  2698. {
  2699. if ( pvListIn == NULL )
  2700. {
  2701. DebugMsg( "DEBUG: ******** Memory leak detected ******************* ThreadID = 0x%08x ********\n", GetCurrentThreadId( ) );
  2702. DebugMsg( "DEBUG: M = Moveable, A = Address, O = Object(new), P = Punk, H = Handle, B = BSTR\n" );
  2703. DebugMsg( "Filename(Line Number): Module Addr/Hndl/Obj Size Comment\n" );
  2704. //" 1 2 3 4 5 6 7 8 "
  2705. //"12345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1....."
  2706. } // if: thread leak
  2707. else
  2708. {
  2709. DebugMsg( "DEBUG: ******** Memory leak detected ******************* %s ********\n", pszListNameIn );
  2710. DebugMsg( "DEBUG: M = Moveable, A = Address, O = Object(new), P = Punk, H = Handle, B = BSTR\n" );
  2711. DebugMsg( "Filename(Line Number): Module Addr/Hndl/Obj Size Comment\n" );
  2712. //" 1 2 3 4 5 6 7 8 "
  2713. //"12345678901234567890123456789012345678901234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1....."
  2714. } // else: list leak
  2715. fFoundLeak = TRUE;
  2716. } // if: leak found
  2717. //
  2718. // Dump the entries.
  2719. //
  2720. while ( pmb != NULL )
  2721. {
  2722. LPCTSTR pszFormat;
  2723. TCHAR szOutput[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  2724. TCHAR szFileLine[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  2725. switch ( pmb->mbtType )
  2726. {
  2727. case mmbtMEMORYALLOCATION:
  2728. {
  2729. if ( pmb->uFlags & GMEM_MOVEABLE )
  2730. {
  2731. pszFormat = TEXT("%-80s %-10s M 0x%08x %-5u \"%s\"\n");
  2732. } // if: moveable
  2733. else
  2734. {
  2735. pszFormat = TEXT("%-80s %-10s A 0x%08x %-5u \"%s\"\n");
  2736. } // else: fixed address
  2737. }
  2738. break;
  2739. case mmbtOBJECT:
  2740. pszFormat = TEXT("%-80s %-10s O 0x%08x %-5u \"%s\"\n");
  2741. break;
  2742. case mmbtPUNK:
  2743. pszFormat = TEXT("%-80s %-10s P 0x%08x %-5u \"%s\"\n");
  2744. break;
  2745. case mmbtHANDLE:
  2746. pszFormat = TEXT("%-80s %-10s H 0x%08x %-5u \"%s\"\n");
  2747. break;
  2748. case mmbtSYSALLOCSTRING:
  2749. pszFormat = TEXT("%-80s %-10s B 0x%08x %-5u \"%s\"\n");
  2750. break;
  2751. default:
  2752. AssertMsg( 0, "Unknown memory block type!" );
  2753. break;
  2754. } // switch: pmb->mbtType
  2755. wnsprintf( szFileLine,
  2756. cchDEBUG_OUTPUT_BUFFER_SIZE,
  2757. g_szFileLine,
  2758. pmb->pszFile,
  2759. pmb->nLine
  2760. );
  2761. wnsprintf( szOutput,
  2762. cchDEBUG_OUTPUT_BUFFER_SIZE,
  2763. pszFormat,
  2764. szFileLine,
  2765. pmb->pszModule,
  2766. pmb->hGlobal,
  2767. pmb->dwBytes,
  2768. pmb->pszComment
  2769. );
  2770. DebugMsg( szOutput );
  2771. pmb = pmb->pNext;
  2772. } // while: something in the list
  2773. //
  2774. // Print trailer if needed.
  2775. //
  2776. if ( fFoundLeak == TRUE )
  2777. {
  2778. DebugMsg( "DEBUG: ***************************** Memory leak detected *****************************\n\n" );
  2779. } // if: leaking
  2780. //
  2781. // Assert if needed.
  2782. //
  2783. if ( IsDebugFlagSet( mtfMEMORYLEAKS ) )
  2784. {
  2785. Assert( !fFoundLeak );
  2786. } // if: yell at leaks
  2787. } //*** DebugMemoryCheck( )
  2788. //////////////////////////////////////////////////////////////////////////////
  2789. //++
  2790. //
  2791. // void
  2792. // DebugCreateMemoryList(
  2793. // LPCTSTR pszFileIn,
  2794. // const int nLineIn,
  2795. // LPCTSTR pszModuleIn,
  2796. // LPVOID * ppvListOut,
  2797. // LPCTSTR pszListNameIn
  2798. // )
  2799. //
  2800. // Description:
  2801. // Creates a memory block list for tracking possible "global" scope
  2802. // memory allocations.
  2803. //
  2804. // Arguments:
  2805. // pszFileIn - Source file of caller.
  2806. // nLineIn - Source line number of caller.
  2807. // pszModuleIn - Source module name of caller.
  2808. // ppvListOut - Location to the store address of the list head.
  2809. // pszListNameIn - Name of the list.
  2810. //
  2811. // Return Values:
  2812. // None.
  2813. //
  2814. //--
  2815. //////////////////////////////////////////////////////////////////////////////
  2816. void
  2817. DebugCreateMemoryList(
  2818. LPCTSTR pszFileIn,
  2819. const int nLineIn,
  2820. LPCTSTR pszModuleIn,
  2821. LPVOID * ppvListOut,
  2822. LPCTSTR pszListNameIn
  2823. )
  2824. {
  2825. MEMORYBLOCKLIST * pmbl;
  2826. Assert( ppvListOut != NULL );
  2827. Assert( *ppvListOut == NULL );
  2828. *ppvListOut = DebugAlloc( pszFileIn, nLineIn, pszModuleIn, GPTR, sizeof(MEMORYBLOCKLIST), TEXT("Memory Tracking List") );
  2829. AssertMsg( * ppvListOut != NULL, "Low memory situation." );
  2830. pmbl = (MEMORYBLOCKLIST*) *ppvListOut;
  2831. Assert( pmbl->lSpinLock == FALSE );
  2832. Assert( pmbl->pmbList == NULL );
  2833. Assert( pmbl->fDeadList == FALSE );
  2834. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  2835. {
  2836. DebugMessage( pszFileIn, nLineIn, pszModuleIn, TEXT("Created new memory list %s\n"), pszListNameIn );
  2837. } // if: tracing
  2838. } // DebugCreateMemoryList( )
  2839. //////////////////////////////////////////////////////////////////////////////
  2840. //++
  2841. //
  2842. // void
  2843. // DebugMemoryListDelete(
  2844. // LPCTSTR pszFileIn,
  2845. // const int nLineIn,
  2846. // LPCTSTR pszModuleIn,
  2847. // HGLOBAL hGlobalIn,
  2848. // LPVOID pvListIn,
  2849. // LPCTSTR pszListNameIn,
  2850. // BOOL fClobberIn
  2851. // )
  2852. //
  2853. // Description:
  2854. // Removes the memory from the tracking list and adds it back to the
  2855. // "per thread" tracking list in order to called DebugMemoryDelete( )
  2856. // to do the proper destruction of the memory. Not highly efficent, but
  2857. // reduces code maintenance by having "destroy" code in one (the most
  2858. // used) location.
  2859. //
  2860. // Arguments:
  2861. // pszFileIn - Source file of caller.
  2862. // nLineIn - Source line number of caller.
  2863. // pszModuleIn - Source module name of caller.
  2864. // hGlobalIn - Memory to be freed.
  2865. // pvListIn - List from which the memory is to be freed.
  2866. // pvListNameIn - Name of the list.
  2867. // fClobberIn - TRUE - destroys memory; FALSE just removes from list.
  2868. //
  2869. // Return Values:
  2870. // None.
  2871. //
  2872. //--
  2873. //////////////////////////////////////////////////////////////////////////////
  2874. void
  2875. DebugMemoryListDelete(
  2876. LPCTSTR pszFileIn,
  2877. const int nLineIn,
  2878. LPCTSTR pszModuleIn,
  2879. HGLOBAL hGlobalIn,
  2880. LPVOID pvListIn,
  2881. LPCTSTR pszListNameIn,
  2882. BOOL fClobberIn
  2883. )
  2884. {
  2885. if ( hGlobalIn != NULL
  2886. && pvListIn != NULL
  2887. )
  2888. {
  2889. MEMORYBLOCK * pmbHead;
  2890. MEMORYBLOCKLIST * pmbl = (MEMORYBLOCKLIST *) pvListIn;
  2891. MEMORYBLOCK * pmbLast = NULL;
  2892. Assert( pszListNameIn != NULL );
  2893. DebugAcquireSpinLock( &pmbl->lSpinLock );
  2894. AssertMsg( pmbl->fDeadList == FALSE, "List was terminated." );
  2895. pmbHead = pmbl->pmbList;
  2896. //
  2897. // Find the memory in the memory block list
  2898. //
  2899. while ( pmbHead != NULL
  2900. && pmbHead->hGlobal != hGlobalIn
  2901. )
  2902. {
  2903. pmbLast = pmbHead;
  2904. pmbHead = pmbLast->pNext;
  2905. } // while: finding the entry in the list
  2906. //
  2907. // Remove the memory block from the tracking list.
  2908. //
  2909. if ( pmbLast != NULL )
  2910. {
  2911. pmbLast->pNext = pmbHead->pNext;
  2912. } // if: not first entry
  2913. else
  2914. {
  2915. pmbl->pmbList = pmbHead->pNext;
  2916. } // else: first entry
  2917. DebugReleaseSpinLock( &pmbl->lSpinLock );
  2918. //
  2919. // Add it back to the per thread list.
  2920. //
  2921. pmbLast = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2922. pmbHead->pNext = pmbLast;
  2923. TlsSetValue( g_TraceMemoryIndex, pmbHead );
  2924. //
  2925. // Finally delete it.
  2926. //
  2927. DebugMemoryDelete( pmbHead->mbtType, pmbHead->hGlobal, pszFileIn, nLineIn, pszModuleIn, fClobberIn );
  2928. } // if: pvIn != NULL
  2929. } // DebugMemoryListDelete( )
  2930. //////////////////////////////////////////////////////////////////////////////
  2931. //++
  2932. //
  2933. // void
  2934. // DebugMoveToMemoryList(
  2935. // LPCTSTR pszFileIn,
  2936. // const int nLineIn,
  2937. // LPCTSTR pszModuleIn,
  2938. // HGLOBAL hGlobalIn,
  2939. // LPVOID pvListIn,
  2940. // LPCTSTR pszListNameIn
  2941. // )
  2942. //
  2943. // Description:
  2944. // Moves the memory pvIn from the per thread tracking list to the thread
  2945. // independent list "pmbListIn". Useful when memory is being handed from
  2946. // one thread to another. Also useful for objects that live past the
  2947. // lifetime of the thread that created them.
  2948. //
  2949. // Arguments:
  2950. // LPCTSTR pszFileIn - Source file of the caller.
  2951. // const int nLineIn - Source line number of the caller.
  2952. // LPCTSTR pszModuleIn - Source module name of the caller.
  2953. // hGlobalIn - Memory to move to list.
  2954. // pvListIn - The list to move to.
  2955. // pszListNameIn - The name of the list.
  2956. //
  2957. // Return Values:
  2958. // None.
  2959. //
  2960. //--
  2961. //////////////////////////////////////////////////////////////////////////////
  2962. void
  2963. DebugMoveToMemoryList(
  2964. LPCTSTR pszFileIn,
  2965. const int nLineIn,
  2966. LPCTSTR pszModuleIn,
  2967. HGLOBAL hGlobalIn,
  2968. LPVOID pvListIn,
  2969. LPCTSTR pszListNameIn
  2970. )
  2971. {
  2972. if ( hGlobalIn != NULL
  2973. && pvListIn != NULL
  2974. )
  2975. {
  2976. MEMORYBLOCKLIST * pmbl = (MEMORYBLOCKLIST *) pvListIn;
  2977. MEMORYBLOCK * pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  2978. MEMORYBLOCK * pmbLast = NULL;
  2979. Assert( pszListNameIn != NULL );
  2980. //
  2981. // Find the memory in the memory block list
  2982. //
  2983. while ( pmbHead != NULL
  2984. && pmbHead->hGlobal != hGlobalIn
  2985. )
  2986. {
  2987. pmbLast = pmbHead;
  2988. pmbHead = pmbLast->pNext;
  2989. } // while: finding the entry in the list
  2990. AssertMsg( pmbHead != NULL, "Memory not in list. Check your code." );
  2991. //
  2992. // Remove the memory block from the "per thread" tracking list.
  2993. //
  2994. if ( pmbLast != NULL )
  2995. {
  2996. pmbLast->pNext = pmbHead->pNext;
  2997. } // if: not first entry
  2998. else
  2999. {
  3000. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  3001. } // else: first entry
  3002. //
  3003. // Update the "source" data.
  3004. //
  3005. pmbHead->pszFile = pszFileIn;
  3006. pmbHead->nLine = nLineIn;
  3007. pmbHead->pszModule = pszModuleIn;
  3008. //
  3009. // Spew if needed.
  3010. //
  3011. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  3012. {
  3013. TCHAR szMessage[ 128 ]; // random
  3014. StrCpy( szMessage, TEXT("Transferring to ") );
  3015. StrCat( szMessage, pszListNameIn );
  3016. DebugMemorySpew( pmbHead, szMessage );
  3017. } // if: tracing
  3018. //
  3019. // Add to list.
  3020. //
  3021. DebugAcquireSpinLock( &pmbl->lSpinLock );
  3022. AssertMsg( pmbl->fDeadList == FALSE, "List was terminated." );
  3023. pmbHead->pNext = pmbl->pmbList;
  3024. pmbl->pmbList = pmbHead;
  3025. DebugReleaseSpinLock( &pmbl->lSpinLock );
  3026. } // if: pvIn != NULL
  3027. } // DebugMoveToMemoryList( )
  3028. #if defined( USES_SYSALLOCSTRING )
  3029. //////////////////////////////////////////////////////////////////////////////
  3030. //++
  3031. //
  3032. // INT
  3033. // DebugSysReAllocString(
  3034. // LPCTSTR pszFileIn,
  3035. // const int nLineIn,
  3036. // LPCTSTR pszModuleIn,
  3037. // BSTR * pbstrIn,
  3038. // const OLECHAR * pszIn,
  3039. // LPCTSTR pszCommentIn
  3040. // )
  3041. //
  3042. // Description:
  3043. // Adds memory tracing to SysReAllocString( ).
  3044. //
  3045. // Arguments:
  3046. // pszFileIn - Source file path
  3047. // nLineIn - Source line number
  3048. // pszModuleIn - Source module name
  3049. // pbstrIn - Pointer to the BSTR to realloc
  3050. // pszIn - String to be copied (see SysReAllocString)
  3051. // pszCommentIn - Comment about alloction
  3052. //
  3053. // Return Values:
  3054. // None.
  3055. //
  3056. //--
  3057. //////////////////////////////////////////////////////////////////////////////
  3058. INT
  3059. DebugSysReAllocString(
  3060. LPCTSTR pszFileIn,
  3061. const int nLineIn,
  3062. LPCTSTR pszModuleIn,
  3063. BSTR * pbstrIn,
  3064. const OLECHAR * pszIn,
  3065. LPCTSTR pszCommentIn
  3066. )
  3067. {
  3068. BSTR bstrOld;
  3069. BSTR bstr;
  3070. MEMORYBLOCK * pmbHead = NULL;
  3071. BOOL fReturn = FALSE;
  3072. //
  3073. // Some assertions that SysReAllocString( ) makes. These would be fatal
  3074. // in retail.
  3075. //
  3076. Assert( pbstrIn != NULL );
  3077. Assert( pszIn != NULL );
  3078. Assert( pszIn < *pbstrIn || pszIn > *pbstrIn + wcslen( *pbstrIn ) + 1 );
  3079. bstrOld = *pbstrIn;
  3080. if ( bstrOld != NULL )
  3081. {
  3082. MEMORYBLOCK * pmbLast = NULL;
  3083. pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  3084. //
  3085. // Find the memory in the memory block list
  3086. //
  3087. while ( pmbHead != NULL
  3088. && pmbHead->bstr != bstrOld
  3089. )
  3090. {
  3091. pmbLast = pmbHead;
  3092. pmbHead = pmbLast->pNext;
  3093. } // while: finding the entry in the list
  3094. if ( pmbHead != NULL )
  3095. {
  3096. AssertMsg( pmbHead->mbtType == mmbtSYSALLOCSTRING, "You can only SysReAlloc sysstring allocations!" );
  3097. //
  3098. // Remove the memory from the tracking list
  3099. //
  3100. if ( pmbLast != NULL )
  3101. {
  3102. pmbLast->pNext = pmbHead->pNext;
  3103. } // if: not first entry
  3104. else
  3105. {
  3106. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  3107. } // else: first entry
  3108. //
  3109. // Spew if needed
  3110. //
  3111. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  3112. {
  3113. DebugMemorySpew( pmbHead, TEXT("Freeing") );
  3114. } // if: tracing
  3115. //
  3116. // Force the programmer to handle a real realloc by moving the
  3117. // memory first.
  3118. //
  3119. bstrOld = SysAllocString( *pbstrIn );
  3120. if ( bstrOld != NULL )
  3121. {
  3122. StrCpy( bstrOld, *pbstrIn );
  3123. pmbHead->bstr = bstrOld;
  3124. } // if: success
  3125. else
  3126. {
  3127. bstrOld = *pbstrIn;
  3128. } // else: failed
  3129. } // if: found entry
  3130. else
  3131. {
  3132. DebugMessage( pszFileIn,
  3133. nLineIn,
  3134. pszModuleIn,
  3135. TEXT("***** Attempted to SysReAlloc 0x%08x not owned by thread (ThreadID = 0x%08x) *****\n"),
  3136. bstrOld,
  3137. GetCurrentThreadId( )
  3138. );
  3139. } // else: entry not found
  3140. } // if: something to delete
  3141. //
  3142. // We do this any way because the flags and input still need to be
  3143. // verified by SysReAllocString( ).
  3144. //
  3145. fReturn = SysReAllocString( &bstrOld, pszIn );
  3146. if ( ! fReturn )
  3147. {
  3148. DWORD dwErr = GetLastError( );
  3149. AssertMsg( dwErr == 0, "GlobalReAlloc() failed!" );
  3150. if ( *pbstrIn != bstrOld )
  3151. {
  3152. SysFreeString( bstrOld );
  3153. } // if: forced a move
  3154. SetLastError( dwErr );
  3155. } // if: allocation failed
  3156. else
  3157. {
  3158. if ( bstrOld != *pbstrIn )
  3159. {
  3160. if ( pmbHead != NULL )
  3161. {
  3162. //
  3163. // Nuke the old memory
  3164. //
  3165. Assert( pmbHead->dwBytes != 0 ); // invalid string
  3166. memset( *pbstrIn, 0xFA, pmbHead->dwBytes );
  3167. } // if: entry found
  3168. //
  3169. // Free the old memory
  3170. //
  3171. SysFreeString( *pbstrIn );
  3172. } // if: new memory location
  3173. if ( pmbHead != NULL )
  3174. {
  3175. //
  3176. // Re-add the tracking block by reusing the old tracking block
  3177. //
  3178. pmbHead->bstr = bstrOld;
  3179. pmbHead->dwBytes = wcslen( pszIn ) + 1;
  3180. // pmbHead->uFlags = uFlagsIn; - not used
  3181. pmbHead->pszFile = pszFileIn;
  3182. pmbHead->nLine = nLineIn;
  3183. pmbHead->pszModule = pszModuleIn;
  3184. pmbHead->pszComment = pszCommentIn;
  3185. pmbHead->pNext = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  3186. TlsSetValue( g_TraceMemoryIndex, (LPVOID) pmbHead );
  3187. //
  3188. // Spew if needed
  3189. //
  3190. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  3191. {
  3192. DebugMemorySpew( pmbHead, TEXT("SysReAlloced") );
  3193. } // if: tracing
  3194. } // if: entry found
  3195. else
  3196. {
  3197. //
  3198. // Create a new block
  3199. //
  3200. DebugMemoryAdd( mmbtSYSALLOCSTRING,
  3201. bstrOld,
  3202. pszFileIn,
  3203. nLineIn,
  3204. pszModuleIn,
  3205. 0,
  3206. wcslen( pszIn ) + 1,
  3207. pszCommentIn
  3208. );
  3209. } // else: make new entry
  3210. } // else: allocation succeeded
  3211. *pbstrIn = bstrOld;
  3212. return fReturn;
  3213. } //*** DebugSysReAllocString( )
  3214. //////////////////////////////////////////////////////////////////////////////
  3215. //++
  3216. //
  3217. // INT
  3218. // DebugSysReAllocStringLen(
  3219. // LPCTSTR pszFileIn,
  3220. // const int nLineIn,
  3221. // LPCTSTR pszModuleIn,
  3222. // BSTR * pbstrIn,
  3223. // const OLECHAR * pszIn,
  3224. // LPCTSTR pszCommentIn
  3225. // )
  3226. //
  3227. // Description:
  3228. // Adds memory tracing to SysReAllocString( ).
  3229. //
  3230. // Arguments:
  3231. // pszFileIn - Source file path
  3232. // nLineIn - Source line number
  3233. // pszModuleIn - Source module name
  3234. // pbstrIn - Pointer to the BSTR to realloc
  3235. // pszIn - String to be copied (see SysReAllocString)
  3236. // pszCommentIn - Comment about alloction
  3237. //
  3238. // Return Values:
  3239. // None.
  3240. //
  3241. //--
  3242. //////////////////////////////////////////////////////////////////////////////
  3243. INT
  3244. DebugSysReAllocStringLen(
  3245. LPCTSTR pszFileIn,
  3246. const int nLineIn,
  3247. LPCTSTR pszModuleIn,
  3248. BSTR * pbstrIn,
  3249. const OLECHAR * pszIn,
  3250. unsigned int ucchIn,
  3251. LPCTSTR pszCommentIn
  3252. )
  3253. {
  3254. BSTR bstrOld;
  3255. BSTR bstr;
  3256. MEMORYBLOCK * pmbHead = NULL;
  3257. BOOL fReturn = FALSE;
  3258. //
  3259. // Some assertions that SysReAllocString( ) makes. These would be fatal
  3260. // in retail.
  3261. //
  3262. Assert( pbstrIn != NULL );
  3263. Assert( pszIn != NULL );
  3264. Assert( pszIn < *pbstrIn || pszIn > *pbstrIn + ucchIn + 1 );
  3265. bstrOld = *pbstrIn;
  3266. if ( bstrOld != NULL )
  3267. {
  3268. MEMORYBLOCK * pmbLast = NULL;
  3269. pmbHead = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  3270. //
  3271. // Find the memory in the memory block list
  3272. //
  3273. while ( pmbHead != NULL
  3274. && pmbHead->bstr != bstrOld
  3275. )
  3276. {
  3277. pmbLast = pmbHead;
  3278. pmbHead = pmbLast->pNext;
  3279. } // while: finding the entry in the list
  3280. if ( pmbHead != NULL )
  3281. {
  3282. AssertMsg( pmbHead->mbtType == mmbtSYSALLOCSTRING, "You can only SysReAlloc sysstring allocations!" );
  3283. //
  3284. // Remove the memory from the tracking list
  3285. //
  3286. if ( pmbLast != NULL )
  3287. {
  3288. pmbLast->pNext = pmbHead->pNext;
  3289. } // if: not first entry
  3290. else
  3291. {
  3292. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  3293. } // else: first entry
  3294. //
  3295. // Spew if needed
  3296. //
  3297. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  3298. {
  3299. DebugMemorySpew( pmbHead, TEXT("Freeing") );
  3300. } // if: tracing
  3301. //
  3302. // Force the programmer to handle a real realloc by moving the
  3303. // memory first.
  3304. //
  3305. bstrOld = SysAllocString( *pbstrIn );
  3306. if ( bstrOld != NULL )
  3307. {
  3308. StrCpy( bstrOld, *pbstrIn );
  3309. pmbHead->bstr = bstrOld;
  3310. } // if: success
  3311. else
  3312. {
  3313. bstrOld = *pbstrIn;
  3314. } // else: failed
  3315. } // if: found entry
  3316. else
  3317. {
  3318. DebugMessage( pszFileIn,
  3319. nLineIn,
  3320. pszModuleIn,
  3321. TEXT("***** Attempted to SysReAlloc 0x%08x not owned by thread (ThreadID = 0x%08x) *****\n"),
  3322. bstrOld,
  3323. GetCurrentThreadId( )
  3324. );
  3325. } // else: entry not found
  3326. } // if: something to delete
  3327. //
  3328. // We do this any way because the flags and input still need to be
  3329. // verified by SysReAllocString( ).
  3330. //
  3331. fReturn = SysReAllocStringLen( &bstrOld, pszIn, ucchIn );
  3332. if ( ! fReturn )
  3333. {
  3334. DWORD dwErr = GetLastError( );
  3335. AssertMsg( dwErr == 0, "GlobalReAlloc() failed!" );
  3336. if ( *pbstrIn != bstrOld )
  3337. {
  3338. SysFreeString( bstrOld );
  3339. } // if: forced a move
  3340. SetLastError( dwErr );
  3341. } // if: allocation failed
  3342. else
  3343. {
  3344. if ( bstrOld != *pbstrIn )
  3345. {
  3346. if ( pmbHead != NULL )
  3347. {
  3348. //
  3349. // Nuke the old memory
  3350. //
  3351. Assert( pmbHead->dwBytes != 0 ); // invalid string
  3352. memset( *pbstrIn, 0xFA, pmbHead->dwBytes );
  3353. } // if: entry found
  3354. //
  3355. // Free the old memory
  3356. //
  3357. SysFreeString( *pbstrIn );
  3358. } // if: new memory location
  3359. if ( pmbHead != NULL )
  3360. {
  3361. //
  3362. // Re-add the tracking block by reusing the old tracking block
  3363. //
  3364. pmbHead->bstr = bstrOld;
  3365. pmbHead->dwBytes = ucchIn;
  3366. // pmbHead->uFlags = uFlagsIn; - not used
  3367. pmbHead->pszFile = pszFileIn;
  3368. pmbHead->nLine = nLineIn;
  3369. pmbHead->pszModule = pszModuleIn;
  3370. pmbHead->pszComment = pszCommentIn;
  3371. pmbHead->pNext = (MEMORYBLOCK *) TlsGetValue( g_TraceMemoryIndex );
  3372. TlsSetValue( g_TraceMemoryIndex, (LPVOID) pmbHead );
  3373. //
  3374. // Spew if needed
  3375. //
  3376. if ( IsTraceFlagSet( mtfMEMORYALLOCS ) )
  3377. {
  3378. DebugMemorySpew( pmbHead, TEXT("SysReAlloced") );
  3379. } // if: tracing
  3380. } // if: entry found
  3381. else
  3382. {
  3383. //
  3384. // Create a new block
  3385. //
  3386. DebugMemoryAdd( mmbtSYSALLOCSTRING,
  3387. bstrOld,
  3388. pszFileIn,
  3389. nLineIn,
  3390. pszModuleIn,
  3391. 0,
  3392. ucchIn + 1,
  3393. pszCommentIn
  3394. );
  3395. } // else: make new entry
  3396. } // else: allocation succeeded
  3397. *pbstrIn = bstrOld;
  3398. return fReturn;
  3399. } //*** DebugSysReAllocStringLen( )
  3400. #endif // USES_SYSALLOCSTRING
  3401. //****************************************************************************
  3402. //
  3403. // Global Management Functions -
  3404. //
  3405. // These are in debug and retail but internally they change
  3406. // depending on the build.
  3407. //
  3408. //****************************************************************************
  3409. //////////////////////////////////////////////////////////////////////////////
  3410. //++
  3411. //
  3412. // DEBUG version
  3413. //
  3414. // void *
  3415. // _cdecl
  3416. // operator new(
  3417. // size_t stSizeIn,
  3418. // LPCTSTR pszFileIn,
  3419. // const int nLineIn,
  3420. // LPCTSTR pszModuleIn
  3421. // )
  3422. //
  3423. // Description:
  3424. // Replacment for the operator new() in the CRTs. This should be used
  3425. // in conjunction with the "new" macro. It will track the allocations.
  3426. //
  3427. // Arguments:
  3428. // stSizeIn - Size of the object to create.
  3429. // pszFileIn - Source filename where the call was made.
  3430. // nLineIn - Source line number where the call was made.
  3431. // pszModuleIn - Source module name where the call was made.
  3432. //
  3433. // Return Values:
  3434. // Void pointer to the new object.
  3435. //
  3436. //--
  3437. //////////////////////////////////////////////////////////////////////////////
  3438. #undef new
  3439. void *
  3440. __cdecl
  3441. operator new(
  3442. size_t stSizeIn,
  3443. LPCTSTR pszFileIn,
  3444. const int nLineIn,
  3445. LPCTSTR pszModuleIn
  3446. )
  3447. {
  3448. HGLOBAL hGlobal = GlobalAlloc( GPTR, stSizeIn );
  3449. return DebugMemoryAdd( mmbtOBJECT,
  3450. hGlobal,
  3451. pszFileIn,
  3452. nLineIn,
  3453. pszModuleIn,
  3454. GPTR,
  3455. stSizeIn,
  3456. TEXT(" new( ) ")
  3457. );
  3458. } //*** operator new( pszFileIn, etc. ) - DEBUG
  3459. //////////////////////////////////////////////////////////////////////////////
  3460. //++
  3461. //
  3462. // DEBUG version
  3463. //
  3464. // void *
  3465. // __cdecl
  3466. // operator new(
  3467. // size_t stSizeIn
  3468. // )
  3469. //
  3470. // Description:
  3471. // Stub to prevent someone from not using the "new" macro or if somehow
  3472. // the new macro was undefined. It routine will always Assert if called.
  3473. //
  3474. // Arguments:
  3475. // stSizeIn - Not used.
  3476. //
  3477. // Return Values:
  3478. // NULL always.
  3479. //
  3480. //--
  3481. //////////////////////////////////////////////////////////////////////////////
  3482. void *
  3483. __cdecl
  3484. operator new(
  3485. size_t stSizeIn
  3486. )
  3487. {
  3488. return GlobalAlloc( GPTR, stSizeIn );
  3489. } //*** operator new( ) - DEBUG
  3490. //////////////////////////////////////////////////////////////////////////////
  3491. //++
  3492. //
  3493. // DEBUG version
  3494. //
  3495. // void
  3496. // __cdecl
  3497. // operator delete(
  3498. // void * pvIn
  3499. // )
  3500. //
  3501. // Description:
  3502. // Replacment for the operator delete() in the CRTs. It will remove the
  3503. // object from the memory allocation tracking table.
  3504. //
  3505. // Arguments:
  3506. // pvIn - Pointer to object being destroyed.
  3507. //
  3508. // Return Value:
  3509. // None.
  3510. //
  3511. //--
  3512. //////////////////////////////////////////////////////////////////////////////
  3513. void
  3514. __cdecl
  3515. operator delete(
  3516. void * pvIn
  3517. )
  3518. {
  3519. DebugMemoryDelete( mmbtOBJECT, pvIn, g_szUnknown, 0, g_szUnknown, TRUE );
  3520. GlobalFree( pvIn );
  3521. } //*** operator delete( ) - DEBUG
  3522. //////////////////////////////////////////////////////////////////////////////
  3523. //++
  3524. //
  3525. // DEBUG version
  3526. //
  3527. // int
  3528. // __cdecl
  3529. // _purecall( void )
  3530. //
  3531. // Description:
  3532. // Stub for purecall functions. It will always Assert.
  3533. //
  3534. // Arguments:
  3535. // None.
  3536. //
  3537. // Return Values:
  3538. // E_UNEXPECTED always.
  3539. //
  3540. //////////////////////////////////////////////////////////////////////////////
  3541. int
  3542. __cdecl
  3543. _purecall( void )
  3544. {
  3545. AssertMsg( 0, "Purecall" );
  3546. return E_UNEXPECTED;
  3547. } //*** _purecall( ) - DEBUG
  3548. #else // ! DEBUG -- It's retail
  3549. //****************************************************************************
  3550. //
  3551. // Global Management Functions -
  3552. //
  3553. // These are the retail version.
  3554. //
  3555. //****************************************************************************
  3556. //////////////////////////////////////////////////////////////////////////////
  3557. //++
  3558. //
  3559. // RETAIL version
  3560. //
  3561. // void *
  3562. // _cdecl
  3563. // operator new(
  3564. // size_t stSizeIn,
  3565. // )
  3566. //
  3567. // Description:
  3568. // Replacment for the operator new() in the CRTs. Simply allocates a
  3569. // block of memory for the object to use.
  3570. //
  3571. // Arguments:
  3572. // stSizeIn - Size of the object to create.
  3573. //
  3574. // Return Values:
  3575. // Void pointer to the new object.
  3576. //
  3577. //--
  3578. //////////////////////////////////////////////////////////////////////////////
  3579. void *
  3580. __cdecl
  3581. operator new(
  3582. size_t stSizeIn
  3583. )
  3584. {
  3585. return LocalAlloc( GPTR, stSizeIn );
  3586. } //*** operator new( ) - RETAIL
  3587. //////////////////////////////////////////////////////////////////////////////
  3588. //++
  3589. //
  3590. // RETAIL version
  3591. //
  3592. // void
  3593. // __cdecl
  3594. // operator delete(
  3595. // void * pvIn
  3596. // )
  3597. //
  3598. // Description:
  3599. // Replacment for the operator delete() in the CRTs. Simply frees the
  3600. // memory.
  3601. //
  3602. // Arguments:
  3603. // pvIn - Pointer to object being destroyed.
  3604. //
  3605. // Return Values:
  3606. // None.
  3607. //
  3608. //--
  3609. //////////////////////////////////////////////////////////////////////////////
  3610. void
  3611. __cdecl
  3612. operator delete(
  3613. void * pv
  3614. )
  3615. {
  3616. LocalFree( pv );
  3617. } //*** operator delete( ) - RETAIL
  3618. //////////////////////////////////////////////////////////////////////////////
  3619. //++
  3620. //
  3621. // RETAIL version
  3622. //
  3623. // int
  3624. // __cdecl
  3625. // _purecall( void )
  3626. //
  3627. // Description:
  3628. // Stub for purecall functions.
  3629. //
  3630. // Arguments:
  3631. // None.
  3632. //
  3633. // Return Values:
  3634. // E_UNEXPECTED always.
  3635. //
  3636. //--
  3637. //////////////////////////////////////////////////////////////////////////////
  3638. int
  3639. __cdecl
  3640. _purecall( void )
  3641. {
  3642. // BUGBUG: DavidP 08-DEC-1999 Shouldn't we assert?
  3643. return E_UNEXPECTED;
  3644. } //*** _purecall( ) - RETAIL
  3645. #define DebugDumpWMITraceFlags( _arg ) // NOP
  3646. #define __MODULE__ NULL
  3647. //
  3648. // TODO: remove this when WMI is more dynamic
  3649. //
  3650. static const int cchDEBUG_OUTPUT_BUFFER_SIZE = 512;
  3651. #endif // DEBUG
  3652. //****************************************************************************
  3653. //****************************************************************************
  3654. //
  3655. // Logging Functions
  3656. //
  3657. // These are in both DEBUG and RETAIL.
  3658. //
  3659. //****************************************************************************
  3660. //****************************************************************************
  3661. //
  3662. // Constants
  3663. //
  3664. static const int LOG_OUTPUT_BUFFER_SIZE = 512;
  3665. //
  3666. // Globals
  3667. //
  3668. CRITICAL_SECTION * g_pcsLogging = NULL;
  3669. HANDLE g_hLogFile = INVALID_HANDLE_VALUE;
  3670. //////////////////////////////////////////////////////////////////////////////
  3671. //++
  3672. //
  3673. // HRESULT
  3674. // HrLogCreateDirectoryPath(
  3675. // LPWSTR pszDirectoryPathInOut
  3676. // )
  3677. //
  3678. // Descriptions:
  3679. // Creates the directory tree as required.
  3680. //
  3681. // Arguments:
  3682. // pszDirectoryPathOut
  3683. // Must be MAX_PATH big. It will contain the log file path to create.
  3684. //
  3685. // Return Values:
  3686. // S_OK - Success
  3687. // other HRESULTs for failures
  3688. //
  3689. //--
  3690. //////////////////////////////////////////////////////////////////////////////
  3691. HRESULT
  3692. HrLogCreateDirectoryPath(
  3693. LPWSTR pszDirectoryPath
  3694. )
  3695. {
  3696. LPTSTR psz;
  3697. BOOL fReturn;
  3698. DWORD dwAttr;
  3699. HRESULT hr = S_OK;
  3700. //
  3701. // Find the \ that indicates the root directory. There should be at least
  3702. // one \, but if there isn't, we just fall through.
  3703. //
  3704. // skip X:\ part
  3705. psz = wcschr( pszDirectoryPath, L'\\' );
  3706. Assert( psz != NULL );
  3707. if ( psz != NULL )
  3708. {
  3709. //
  3710. // Find the \ that indicates the end of the first level directory. It's
  3711. // probable that there won't be another \, in which case we just fall
  3712. // through to creating the entire path.
  3713. //
  3714. psz = wcschr( psz + 1, L'\\' );
  3715. while ( psz != NULL )
  3716. {
  3717. // Terminate the directory path at the current level.
  3718. *psz = 0;
  3719. //
  3720. // Create a directory at the current level.
  3721. //
  3722. dwAttr = GetFileAttributes( pszDirectoryPath );
  3723. if ( 0xFFFFffff == dwAttr )
  3724. {
  3725. DebugMsg( "DEBUG: Creating %s\n", pszDirectoryPath );
  3726. fReturn = CreateDirectory( pszDirectoryPath, NULL );
  3727. if ( ! fReturn )
  3728. {
  3729. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3730. goto Error;
  3731. } // if: creation failed
  3732. } // if: directory not found
  3733. else if ( ( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) == 0 )
  3734. {
  3735. hr = THR( E_FAIL );
  3736. goto Error;
  3737. } // else: file found
  3738. //
  3739. // Restore the \ and find the next one.
  3740. //
  3741. *psz = L'\\';
  3742. psz = wcschr( psz + 1, L'\\' );
  3743. } // while: found slash
  3744. } // if: found slash
  3745. //
  3746. // Create the target directory.
  3747. //
  3748. dwAttr = GetFileAttributes( pszDirectoryPath );
  3749. if ( 0xFFFFffff == dwAttr )
  3750. {
  3751. fReturn = CreateDirectory( pszDirectoryPath, NULL );
  3752. if ( ! fReturn )
  3753. {
  3754. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3755. } // if: creation failed
  3756. } // if: path not found
  3757. Error:
  3758. return hr;
  3759. } //*** HrCreateDirectoryPath( )
  3760. //////////////////////////////////////////////////////////////////////////////
  3761. //++
  3762. //
  3763. // HRESULT
  3764. // HrLogOpen( void )
  3765. //
  3766. // Description:
  3767. // This function:
  3768. // - initializes the log critical section
  3769. // - enters the log critical section assuring only one thread is
  3770. // writing to the log at a time
  3771. // - creates the directory tree to the log file (if needed)
  3772. // - initializes the log file by:
  3773. // - creating a new log file if one doesn't exist.
  3774. // - opens an existing log file (for append)
  3775. // - appends a time/date stamp that the log was (re)opened.
  3776. //
  3777. // Use LogClose() to exit the log critical section.
  3778. //
  3779. // If there is a failure inside this function, the log critical
  3780. // section will be released before returning.
  3781. //
  3782. // Arguments:
  3783. // None.
  3784. //
  3785. // Return Values:
  3786. // S_OK - log critical section held and log open successfully
  3787. // Otherwize HRESULT error code.
  3788. //
  3789. //--
  3790. //////////////////////////////////////////////////////////////////////////////
  3791. HRESULT
  3792. HrLogOpen( void )
  3793. {
  3794. TCHAR szFilePath[ MAX_PATH ];
  3795. TCHAR szModulePath[ MAX_PATH ];
  3796. CHAR szBuffer[ LOG_OUTPUT_BUFFER_SIZE ];
  3797. DWORD dwWritten;
  3798. HANDLE hTemp;
  3799. BOOL fReturn;
  3800. HRESULT hr;
  3801. SYSTEMTIME SystemTime;
  3802. //
  3803. // Create a critical section to prevent lines from being fragmented.
  3804. //
  3805. if ( g_pcsLogging == NULL )
  3806. {
  3807. PCRITICAL_SECTION pNewCritSect =
  3808. (PCRITICAL_SECTION) LocalAlloc( LPTR, sizeof( CRITICAL_SECTION ) );
  3809. if ( pNewCritSect == NULL )
  3810. {
  3811. DebugMsg( "DEBUG: Out of Memory. Logging disabled.\nv" );
  3812. hr = E_OUTOFMEMORY;
  3813. goto Cleanup;
  3814. } // if: creation failed
  3815. InitializeCriticalSection( pNewCritSect );
  3816. // Make sure we only have one log critical section
  3817. InterlockedCompareExchangePointer( (PVOID *) &g_pcsLogging, pNewCritSect, 0 );
  3818. if ( g_pcsLogging != pNewCritSect )
  3819. {
  3820. DebugMsg( "DEBUG: Another thread already created the CS. Deleting this one.\n" );
  3821. DeleteCriticalSection( pNewCritSect );
  3822. LocalFree( pNewCritSect );
  3823. } // if: already have another critical section
  3824. } // if: no critical section created yet
  3825. Assert( g_pcsLogging != NULL );
  3826. EnterCriticalSection( g_pcsLogging );
  3827. //
  3828. // Make sure the log file is open
  3829. //
  3830. if ( g_hLogFile == INVALID_HANDLE_VALUE )
  3831. {
  3832. DWORD dwLen;
  3833. LPTSTR psz;
  3834. //
  3835. // Create the directory tree
  3836. //
  3837. ExpandEnvironmentStrings( TEXT("%windir%\\debug"), szFilePath, MAX_PATH );
  3838. hr = HrLogCreateDirectoryPath( szFilePath );
  3839. if ( FAILED( hr ) )
  3840. {
  3841. #if defined( DEBUG )
  3842. if ( !( g_tfModule & mtfOUTPUTTODISK ) )
  3843. {
  3844. DebugMsg( "*ERROR* Failed to create directory tree %s\n", szFilePath );
  3845. } // if: not logging to disk
  3846. #endif
  3847. goto Error;
  3848. } // if: failed
  3849. //
  3850. // Add filename
  3851. //
  3852. dwLen = GetModuleFileName( g_hInstance, szModulePath, sizeof( szModulePath ) / sizeof( szModulePath[ 0 ] ) );
  3853. Assert( dwLen != 0 );
  3854. StrCpy( &szModulePath[ dwLen - 3 ], TEXT("log") );
  3855. psz = StrRChr( szModulePath, &szModulePath[ dwLen ], TEXT('\\') );
  3856. Assert( psz != NULL );
  3857. if ( psz == NULL )
  3858. {
  3859. hr = THR( E_POINTER );
  3860. goto Error;
  3861. }
  3862. StrCat( szFilePath, psz );
  3863. //
  3864. // Create it
  3865. //
  3866. g_hLogFile = CreateFile( szFilePath,
  3867. GENERIC_WRITE,
  3868. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3869. NULL,
  3870. OPEN_ALWAYS,
  3871. FILE_FLAG_WRITE_THROUGH,
  3872. NULL
  3873. );
  3874. if ( g_hLogFile == INVALID_HANDLE_VALUE )
  3875. {
  3876. #if defined( DEBUG )
  3877. if ( !( g_tfModule & mtfOUTPUTTODISK ) )
  3878. {
  3879. DebugMsg( "*ERROR* Failed to create log at %s\n", szFilePath );
  3880. } // if: not logging to disk
  3881. #endif
  3882. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3883. goto Error;
  3884. } // if: failed
  3885. // Seek to the end
  3886. SetFilePointer( g_hLogFile, 0, NULL, FILE_END );
  3887. //
  3888. // Write the time/date the log was (re)openned.
  3889. //
  3890. GetLocalTime( &SystemTime );
  3891. wnsprintfA( szBuffer,
  3892. LOG_OUTPUT_BUFFER_SIZE,
  3893. "*\n* %02u/%02u/%04u %02u:%02u:%02u.%03u\n*\n",
  3894. SystemTime.wMonth,
  3895. SystemTime.wDay,
  3896. SystemTime.wYear,
  3897. SystemTime.wHour,
  3898. SystemTime.wMinute,
  3899. SystemTime.wSecond,
  3900. SystemTime.wMilliseconds
  3901. );
  3902. fReturn = WriteFile( g_hLogFile, szBuffer, StrLenA(szBuffer), &dwWritten, NULL );
  3903. if ( ! fReturn )
  3904. {
  3905. hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
  3906. goto Error;
  3907. } // if: failed
  3908. DebugMsg( "DEBUG: Created log at %s\n", szFilePath );
  3909. } // if: file not already openned
  3910. hr = S_OK;
  3911. Cleanup:
  3912. return hr;
  3913. Error:
  3914. DebugMsg( "LogOpen: Failed hr = 0x%08x\n", hr );
  3915. if ( g_hLogFile != INVALID_HANDLE_VALUE )
  3916. {
  3917. CloseHandle( g_hLogFile );
  3918. g_hLogFile = INVALID_HANDLE_VALUE;
  3919. } // if: handle was open
  3920. LeaveCriticalSection( g_pcsLogging );
  3921. goto Cleanup;
  3922. } //*** HrLogOpen( )
  3923. //////////////////////////////////////////////////////////////////////////////
  3924. //++
  3925. //
  3926. // HRESULT
  3927. // HrLogClose( void )
  3928. //
  3929. // Description:
  3930. // This actually just leaves the log critical section.
  3931. //
  3932. // Arguments:
  3933. // None.
  3934. //
  3935. // Return Values:
  3936. // S_OK always.
  3937. //
  3938. //--
  3939. //////////////////////////////////////////////////////////////////////////////
  3940. HRESULT
  3941. HrLogClose( void )
  3942. {
  3943. Assert( g_pcsLogging != NULL );
  3944. LeaveCriticalSection( g_pcsLogging );
  3945. return S_OK;
  3946. } //*** HrLogClose( )
  3947. //////////////////////////////////////////////////////////////////////////////
  3948. //++
  3949. //
  3950. // void
  3951. // LogDateTime( void )
  3952. //
  3953. // Description:
  3954. // Adds date/time stamp to the log without a CR. This should be done
  3955. // while holding the Logging critical section which is done by calling
  3956. // HrLogOpen( ).
  3957. //
  3958. // Arguments:
  3959. // None.
  3960. //
  3961. // Return Values:
  3962. // None.
  3963. //
  3964. //--
  3965. //////////////////////////////////////////////////////////////////////////////
  3966. void
  3967. LogDateTime( void )
  3968. {
  3969. static CHAR szBuffer[ 25 ];
  3970. static SYSTEMTIME OldSystemTime = { 0 };
  3971. static DWORD dwWritten;
  3972. SYSTEMTIME SystemTime;
  3973. DWORD dwWhoCares;
  3974. int iCmp;
  3975. GetLocalTime( &SystemTime );
  3976. //
  3977. // Avoid expensive printf by comparing times
  3978. //
  3979. iCmp = memcmp( (PVOID) &SystemTime, (PVOID) &OldSystemTime, sizeof( SYSTEMTIME ) );
  3980. if ( iCmp != 0 )
  3981. {
  3982. dwWritten = wnsprintfA( szBuffer,
  3983. LOG_OUTPUT_BUFFER_SIZE,
  3984. "%02u/%02u/%04u %02u:%02u:%02u.%03u ",
  3985. SystemTime.wMonth,
  3986. SystemTime.wDay,
  3987. SystemTime.wYear,
  3988. SystemTime.wHour,
  3989. SystemTime.wMinute,
  3990. SystemTime.wSecond,
  3991. SystemTime.wMilliseconds
  3992. );
  3993. Assert( dwWritten < 25 && dwWritten != -1 );
  3994. CopyMemory( (PVOID) &OldSystemTime, (PVOID) &SystemTime, sizeof( SYSTEMTIME ) );
  3995. } // if: time last different from this time
  3996. WriteFile( g_hLogFile, szBuffer, dwWritten, &dwWhoCares, NULL );
  3997. } //*** LogDateTime( )
  3998. //////////////////////////////////////////////////////////////////////////////
  3999. //++
  4000. //
  4001. // ASCII
  4002. //
  4003. // void
  4004. // LogMsg(
  4005. // LPCSTR pszFormat,
  4006. // ...
  4007. // )
  4008. //
  4009. // Description:
  4010. // Logs a message to the log file.
  4011. //
  4012. // Arguments:
  4013. // pszFormat - A printf format string to be printed.
  4014. // ,,, - Arguments for the printf string.
  4015. //
  4016. // Return Values:
  4017. // None.
  4018. //
  4019. //--
  4020. //////////////////////////////////////////////////////////////////////////////
  4021. void
  4022. LogMsg(
  4023. LPCSTR pszFormat,
  4024. ...
  4025. )
  4026. {
  4027. va_list valist;
  4028. CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
  4029. DWORD dwWritten;
  4030. HRESULT hr;
  4031. #ifdef UNICODE
  4032. WCHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
  4033. WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
  4034. mbstowcs( szFormat, pszFormat, StrLenA( pszFormat ) + 1 );
  4035. va_start( valist, pszFormat );
  4036. wvsprintf( szTmpBuf, szFormat, valist);
  4037. va_end( valist );
  4038. dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
  4039. if ( dwWritten == - 1 )
  4040. {
  4041. dwWritten = StrLenA( szBuf );
  4042. } // if: bad character found
  4043. #else
  4044. va_start( valist, pszFormat );
  4045. dwWritten = wvsprintf( szBuf, pszFormat, valist);
  4046. va_end( valist );
  4047. #endif // UNICODE
  4048. hr = HrLogOpen( );
  4049. if ( hr != S_OK )
  4050. {
  4051. return;
  4052. } // if: failed
  4053. // LogDateTime( );
  4054. WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
  4055. HrLogClose( );
  4056. } //*** LogMsg( ) ASCII
  4057. //////////////////////////////////////////////////////////////////////////////
  4058. //++
  4059. //
  4060. // UNICODE
  4061. //
  4062. // void
  4063. // LogMsg(
  4064. // LPCWSTR pszFormat,
  4065. // ...
  4066. // )
  4067. //
  4068. // Description:
  4069. // Logs a message to the log file.
  4070. //
  4071. // Arguments:
  4072. // pszFormat - A printf format string to be printed.
  4073. // ,,, - Arguments for the printf string.
  4074. //
  4075. // Return Values:
  4076. // None.
  4077. //
  4078. //--
  4079. //////////////////////////////////////////////////////////////////////////////
  4080. void
  4081. LogMsg(
  4082. LPCWSTR pszFormat,
  4083. ...
  4084. )
  4085. {
  4086. va_list valist;
  4087. CHAR szBuf[ LOG_OUTPUT_BUFFER_SIZE ];
  4088. DWORD dwWritten;
  4089. HRESULT hr;
  4090. #ifdef UNICODE
  4091. WCHAR szTmpBuf[ LOG_OUTPUT_BUFFER_SIZE ];
  4092. va_start( valist, pszFormat );
  4093. wvsprintf( szTmpBuf, pszFormat, valist);
  4094. va_end( valist );
  4095. dwWritten = wcstombs( szBuf, szTmpBuf, wcslen( szTmpBuf ) + 1 );
  4096. if ( dwWritten == -1 )
  4097. {
  4098. dwWritten = StrLenA( szBuf );
  4099. } // if: bad character found
  4100. #else
  4101. CHAR szFormat[ LOG_OUTPUT_BUFFER_SIZE ];
  4102. wcstombs( szFormat, pszFormat, wcslen( pszFormat ) + 1 );
  4103. va_start( valist, pszFormat );
  4104. dwWritten = wvsprintf( szBuf, szFormat, valist);
  4105. va_end( valist );
  4106. #endif // UNICODE
  4107. hr = HrLogOpen( );
  4108. if ( hr != S_OK )
  4109. {
  4110. return;
  4111. } // if: failed
  4112. // LogDateTime( );
  4113. WriteFile( g_hLogFile, szBuf, dwWritten, &dwWritten, NULL );
  4114. HrLogClose( );
  4115. } //*** LogMsg( ) UNICODE
  4116. //////////////////////////////////////////////////////////////////////////////
  4117. //++
  4118. //
  4119. // void
  4120. // LogTerminiateProcess( void )
  4121. //
  4122. // Description:
  4123. // Cleans up anything the logging routines may have created or
  4124. // initialized. Typical called from the TraceTerminateProcess() macro.
  4125. //
  4126. // Arugments:
  4127. // None.
  4128. //
  4129. // Return Values:
  4130. // None.
  4131. //
  4132. //--
  4133. //////////////////////////////////////////////////////////////////////////////
  4134. void
  4135. LogTerminateProcess( void )
  4136. {
  4137. } //*** LogTerminateProcess( )
  4138. //****************************************************************************
  4139. //
  4140. // WMI Tracing Routines
  4141. //
  4142. // These routines are in both DEBUG and RETAIL versions.
  4143. //
  4144. //****************************************************************************
  4145. //////////////////////////////////////////////////////////////////////////////
  4146. //++
  4147. //
  4148. // ULONG
  4149. // UlWMIControlCallback(
  4150. // IN WMIDPREQUESTCODE RequestCode,
  4151. // IN PVOID RequestContext,
  4152. // IN OUT ULONG * BufferSize,
  4153. // IN OUT PVOID Buffer
  4154. // )
  4155. //
  4156. // Description:
  4157. // WMI's tracing control callback entry point.
  4158. //
  4159. // Arguments:
  4160. // See EVNTRACE.H
  4161. //
  4162. // Return Values:
  4163. // ERROR_SUCCESS - success.
  4164. // ERROR_INVALID_PARAMETER - invalid RequestCode passed in.
  4165. //
  4166. //--
  4167. //////////////////////////////////////////////////////////////////////////////
  4168. ULONG
  4169. WINAPI
  4170. UlWMIControlCallback(
  4171. IN WMIDPREQUESTCODE RequestCode,
  4172. IN PVOID RequestContext,
  4173. IN OUT ULONG * BufferSize,
  4174. IN OUT PVOID Buffer
  4175. )
  4176. {
  4177. ULONG ulResult = ERROR_SUCCESS;
  4178. DEBUG_WMI_CONTROL_GUIDS * pdwcg = (DEBUG_WMI_CONTROL_GUIDS *) RequestContext;
  4179. switch ( RequestCode )
  4180. {
  4181. case WMI_ENABLE_EVENTS:
  4182. {
  4183. TRACEHANDLE hTrace;
  4184. if ( pdwcg->hTrace == NULL )
  4185. {
  4186. hTrace = GetTraceLoggerHandle( Buffer );
  4187. } // if:
  4188. else
  4189. {
  4190. hTrace = pdwcg->hTrace;
  4191. } // else:
  4192. pdwcg->dwFlags = GetTraceEnableFlags( hTrace );
  4193. pdwcg->bLevel = GetTraceEnableLevel( hTrace );
  4194. if ( pdwcg->dwFlags == 0 )
  4195. {
  4196. if ( pdwcg->pMapLevelToFlags != NULL
  4197. && pdwcg->bSizeOfLevelList != 0
  4198. )
  4199. {
  4200. if ( pdwcg->bLevel >= pdwcg->bSizeOfLevelList )
  4201. {
  4202. pdwcg->bLevel = pdwcg->bSizeOfLevelList - 1;
  4203. }
  4204. pdwcg->dwFlags = pdwcg->pMapLevelToFlags[ pdwcg->bLevel ].dwFlags;
  4205. DebugMsg( "DEBUG: WMI tracing level set to %u - %s, flags = 0x%08x\n",
  4206. pdwcg->pszName,
  4207. pdwcg->bLevel,
  4208. pdwcg->pMapLevelToFlags[ pdwcg->bLevel ].pszName,
  4209. pdwcg->dwFlags
  4210. );
  4211. } // if: level->flag mapping available
  4212. else
  4213. {
  4214. DebugMsg( "DEBUG: WMI tracing level set to %u, flags = 0x%08x\n",
  4215. pdwcg->pszName,
  4216. pdwcg->bLevel,
  4217. pdwcg->dwFlags
  4218. );
  4219. } // else: no mappings
  4220. } // if: no flags set
  4221. else
  4222. {
  4223. DebugMsg( "DEBUG: WMI tracing level set to %u, flags = 0x%08x\n",
  4224. pdwcg->pszName,
  4225. pdwcg->bLevel,
  4226. pdwcg->dwFlags
  4227. );
  4228. } // else: flags set
  4229. DebugDumpWMITraceFlags( pdwcg );
  4230. pdwcg->hTrace = hTrace;
  4231. } // WMI_ENABLE_EVENTS
  4232. break;
  4233. case WMI_DISABLE_EVENTS:
  4234. pdwcg->dwFlags = 0;
  4235. pdwcg->bLevel = 0;
  4236. pdwcg->hTrace = NULL;
  4237. DebugMsg( "DEBUG: %s WMI tracing disabled.\n", pdwcg->pszName );
  4238. break;
  4239. default:
  4240. ulResult = ERROR_INVALID_PARAMETER;
  4241. break;
  4242. } // switch: RequestCode
  4243. return ulResult;
  4244. } //*** UlWMIControlCallback( )
  4245. //////////////////////////////////////////////////////////////////////////////
  4246. //++
  4247. //
  4248. // void
  4249. // WMIInitializeTracing(
  4250. // DEBUG_WMI_CONTROL_GUIDS dwcgControlListIn[],
  4251. // int nCountOfCOntrolGuidsIn
  4252. // )
  4253. //
  4254. // Description:
  4255. // Initialize the WMI tracing.
  4256. //
  4257. // Arguments:
  4258. // None.
  4259. //
  4260. // Return Values:
  4261. // None.
  4262. //
  4263. //--
  4264. //////////////////////////////////////////////////////////////////////////////
  4265. void
  4266. WMIInitializeTracing(
  4267. DEBUG_WMI_CONTROL_GUIDS dwcgControlListIn[],
  4268. int nCountOfControlGuidsIn
  4269. )
  4270. {
  4271. TCHAR szPath[ MAX_PATH ];
  4272. ULONG ulStatus;
  4273. int nCount;
  4274. #if defined( DEBUG )
  4275. static BOOL fRegistered = FALSE;
  4276. AssertMsg( fRegistered == FALSE, "Re-entrance into InitializeWMITracing!!!" );
  4277. #endif // DEBUG
  4278. GetModuleFileName( g_hInstance, szPath, MAX_PATH );
  4279. for( nCount = 0; nCount < nCountOfControlGuidsIn; nCount++ )
  4280. {
  4281. TRACE_GUID_REGISTRATION * pList;
  4282. pList = (TRACE_GUID_REGISTRATION *)
  4283. LocalAlloc( LMEM_FIXED,
  4284. sizeof( TRACE_GUID_REGISTRATION ) * dwcgControlListIn[ nCount ].dwSizeOfTraceList );
  4285. if ( pList != NULL )
  4286. {
  4287. CopyMemory( pList,
  4288. dwcgControlListIn[ nCount ].pTraceList,
  4289. sizeof( TRACE_GUID_REGISTRATION ) * dwcgControlListIn[ nCount ].dwSizeOfTraceList );
  4290. ulStatus = RegisterTraceGuids( UlWMIControlCallback, // IN RequestAddress
  4291. dwcgControlListIn, // IN RequestContext
  4292. dwcgControlListIn[ nCount ].guidControl, // IN ControlGuid
  4293. dwcgControlListIn[ nCount ].dwSizeOfTraceList, // IN GuidCount
  4294. pList, // IN GuidReg
  4295. (LPCTSTR) szPath, // IN MofImagePath
  4296. __MODULE__, // IN MofResourceName
  4297. &dwcgControlListIn[ nCount ].hRegistration // OUT RegistrationHandle
  4298. );
  4299. AssertMsg( ulStatus == ERROR_SUCCESS, "Trace registration failed\n" );
  4300. LocalFree( pList );
  4301. } // if: list allocated successfully
  4302. } // for: each control GUID
  4303. #if defined( DEBUG )
  4304. fRegistered = TRUE;
  4305. #endif // DEBUG
  4306. } //*** WMIInitializeTracing( )
  4307. //////////////////////////////////////////////////////////////////////////////
  4308. //++
  4309. //
  4310. // void
  4311. // WMITerminateTracing(
  4312. // DEBUG_WMI_CONTROL_GUIDS dwcgControlListIn[],
  4313. // int nCountOfCOntrolGuidsIn
  4314. // )
  4315. //
  4316. // Description:
  4317. // Terminates WMI tracing and unregisters the interfaces.
  4318. //
  4319. // Arguments:
  4320. // dwcgControlListIn -
  4321. // nCountOfControlGuidsIn -
  4322. //
  4323. // Return Values:
  4324. // None.
  4325. //
  4326. //--
  4327. //////////////////////////////////////////////////////////////////////////////
  4328. void
  4329. WMITerminateTracing(
  4330. DEBUG_WMI_CONTROL_GUIDS dwcgControlListIn[],
  4331. int nCountOfControlGuidsIn
  4332. )
  4333. {
  4334. int nCount;
  4335. for( nCount = 0; nCount < nCountOfControlGuidsIn; nCount++ )
  4336. {
  4337. dwcgControlListIn[ nCount ].dwFlags = 0;
  4338. dwcgControlListIn[ nCount ].bLevel = 0;
  4339. dwcgControlListIn[ nCount ].hTrace = NULL;
  4340. UnregisterTraceGuids( dwcgControlListIn[ nCount ].hRegistration );
  4341. } // for: each control GUID
  4342. } //*** WMITerminateTracing( )
  4343. typedef struct
  4344. {
  4345. EVENT_TRACE_HEADER EHeader; // storage for the WMI trace event header
  4346. BYTE bSize; // Size of the string - MAX 255!
  4347. WCHAR szMsg[ cchDEBUG_OUTPUT_BUFFER_SIZE ]; // Message
  4348. } DEBUG_WMI_EVENT_W;
  4349. typedef struct
  4350. {
  4351. EVENT_TRACE_HEADER EHeader; // storage for the WMI trace event header
  4352. BYTE bSize; // Size of the string - MAX 255!
  4353. CHAR szMsg[ cchDEBUG_OUTPUT_BUFFER_SIZE ]; // Message
  4354. } DEBUG_WMI_EVENT_A;
  4355. //////////////////////////////////////////////////////////////////////////////
  4356. //++
  4357. //
  4358. // void
  4359. // WMIMessageByFlags(
  4360. // DEBUG_WMI_CONTROL_GUIDS * pEntryIn,
  4361. // const DWORD dwFlagsIn,
  4362. // LPCWSTR pszFormatIn,
  4363. // ...
  4364. // )
  4365. //
  4366. // Description:
  4367. //
  4368. // Arguments:
  4369. // pEntry -
  4370. // dwFlagsIn -
  4371. // pszFormatIn -
  4372. // ... -
  4373. //
  4374. // Return Values:
  4375. // None.
  4376. //
  4377. //--
  4378. //////////////////////////////////////////////////////////////////////////////
  4379. void
  4380. WMIMessageByFlags(
  4381. DEBUG_WMI_CONTROL_GUIDS * pEntry,
  4382. const DWORD dwFlagsIn,
  4383. LPCWSTR pszFormatIn,
  4384. ...
  4385. )
  4386. {
  4387. va_list valist;
  4388. if ( pEntry->hTrace == NULL )
  4389. {
  4390. return; // NOP
  4391. } // if: no trace logger
  4392. if ( dwFlagsIn == mtfALWAYS
  4393. || pEntry->dwFlags & dwFlagsIn
  4394. )
  4395. {
  4396. ULONG ulStatus;
  4397. DEBUG_WMI_EVENT_W DebugEvent;
  4398. PEVENT_TRACE_HEADER peth = (PEVENT_TRACE_HEADER ) &DebugEvent;
  4399. PWNODE_HEADER pwnh = (PWNODE_HEADER) &DebugEvent;
  4400. ZeroMemory( &DebugEvent, sizeof( DebugEvent ) );
  4401. #ifndef UNICODE
  4402. TCHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  4403. wcstombs( szFormat, pszFormatIn, StrLenW( pszFormatIn ) + 1 );
  4404. va_start( valist, pszFormatIn );
  4405. wvnsprintf( DebugEvent.szMsg, 256,szFormat, valist);
  4406. va_end( valist );
  4407. #else
  4408. va_start( valist, pszFormatIn );
  4409. wvnsprintf( DebugEvent.szMsg, 256,pszFormatIn, valist);
  4410. va_end( valist );
  4411. #endif // UNICODE
  4412. //
  4413. // Fill in the blanks
  4414. //
  4415. DebugEvent.bSize = (BYTE) wcslen( DebugEvent.szMsg );
  4416. peth->Size = sizeof( DebugEvent );
  4417. peth->Class.Type = 10;
  4418. peth->Class.Level = pEntry->bLevel;
  4419. // peth->Class.Version = 0;
  4420. // peth->ThreadId = GetCurrentThreadId( ); - done by system
  4421. pwnh->Guid = *pEntry->guidControl;
  4422. // peth->ClientContext = NULL;
  4423. pwnh->Flags = WNODE_FLAG_TRACED_GUID;
  4424. // GetSystemTimeAsFileTime( (FILETIME *) &peth->TimeStamp ); - done by the system
  4425. ulStatus = TraceEvent( pEntry->hTrace, (PEVENT_TRACE_HEADER) &DebugEvent );
  4426. } // if: flags set
  4427. } //*** WMIMsg( )
  4428. //////////////////////////////////////////////////////////////////////////////
  4429. //++
  4430. //
  4431. // void
  4432. // WMIMessageByFlagsAndLevel(
  4433. // DEBUG_WMI_CONTROL_GUIDS * pEntry,
  4434. // const DWORD dwFlagsIn,
  4435. // const BYTE bLogLevelIn,
  4436. // LPCWSTR pszFormatIn,
  4437. // ...
  4438. // )
  4439. //
  4440. // Description:
  4441. //
  4442. // Arguments:
  4443. // pEntry -
  4444. // dwFlagsIn -
  4445. // bLogLevelIn -
  4446. // pszFormatIn -
  4447. // ... -
  4448. //
  4449. // Return Values:
  4450. // None.
  4451. //
  4452. //--
  4453. //////////////////////////////////////////////////////////////////////////////
  4454. void
  4455. WMIMessageByFlagsAndLevel(
  4456. DEBUG_WMI_CONTROL_GUIDS * pEntry,
  4457. const DWORD dwFlagsIn,
  4458. const BYTE bLogLevelIn,
  4459. LPCWSTR pszFormatIn,
  4460. ...
  4461. )
  4462. {
  4463. va_list valist;
  4464. if ( pEntry->hTrace == NULL )
  4465. {
  4466. return; // NOP
  4467. } // if: no trace logger
  4468. if ( bLogLevelIn > pEntry->bLevel )
  4469. {
  4470. return; // NOP
  4471. } // if: level not high enough
  4472. if ( dwFlagsIn == mtfALWAYS
  4473. || pEntry->dwFlags & dwFlagsIn
  4474. )
  4475. {
  4476. ULONG ulStatus;
  4477. DEBUG_WMI_EVENT_W DebugEvent;
  4478. PEVENT_TRACE_HEADER peth = (PEVENT_TRACE_HEADER ) &DebugEvent;
  4479. PWNODE_HEADER pwnh = (PWNODE_HEADER) &DebugEvent;
  4480. ZeroMemory( &DebugEvent, sizeof( DebugEvent ) );
  4481. #ifndef UNICODE
  4482. TCHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  4483. wcstombs( szFormat, pszFormatIn, StrLenW( pszFormatIn ) + 1 );
  4484. va_start( valist, pszFormatIn );
  4485. wvnsprintf( DebugEvent.szMsg, 256,szFormat, valist);
  4486. va_end( valist );
  4487. #else
  4488. va_start( valist, pszFormatIn );
  4489. wvnsprintf( DebugEvent.szMsg, 256,pszFormatIn, valist);
  4490. va_end( valist );
  4491. #endif // UNICODE
  4492. //
  4493. // Fill in the blanks
  4494. //
  4495. DebugEvent.bSize = (BYTE) wcslen( DebugEvent.szMsg );
  4496. peth->Size = sizeof( DebugEvent );
  4497. peth->Class.Type = 10;
  4498. peth->Class.Level = pEntry->bLevel;
  4499. // peth->Class.Version = 0;
  4500. // peth->ThreadId = GetCurrentThreadId( ); - done by system
  4501. pwnh->Guid = *pEntry->guidControl;
  4502. // peth->ClientContext = NULL;
  4503. pwnh->Flags = WNODE_FLAG_TRACED_GUID;
  4504. // GetSystemTimeAsFileTime( (FILETIME *) &peth->TimeStamp ); - done by the system
  4505. ulStatus = TraceEvent( pEntry->hTrace, (PEVENT_TRACE_HEADER) &DebugEvent );
  4506. } // if: flags set
  4507. } //*** WMIMessageByFlagsAndLevel( )
  4508. //////////////////////////////////////////////////////////////////////////////
  4509. //++
  4510. //
  4511. // void
  4512. // WMIMessageByLevel(
  4513. // DEBUG_WMI_CONTROL_GUIDS * pEntry,
  4514. // const BYTE bLogLevelIn,
  4515. // LPCWSTR pszFormatIn,
  4516. // ...
  4517. // )
  4518. //
  4519. // Description:
  4520. //
  4521. // Arguments:
  4522. // pEntry -
  4523. // bLogLevelIn -
  4524. // pszFormatIn -
  4525. // ... -
  4526. //
  4527. // Return Values:
  4528. // None.
  4529. //
  4530. //--
  4531. //////////////////////////////////////////////////////////////////////////////
  4532. void
  4533. WMIMessageByLevel(
  4534. DEBUG_WMI_CONTROL_GUIDS * pEntry,
  4535. const BYTE bLogLevelIn,
  4536. LPCWSTR pszFormatIn,
  4537. ...
  4538. )
  4539. {
  4540. ULONG ulStatus;
  4541. DEBUG_WMI_EVENT_W DebugEvent;
  4542. PEVENT_TRACE_HEADER peth = (PEVENT_TRACE_HEADER ) &DebugEvent;
  4543. PWNODE_HEADER pwnh = (PWNODE_HEADER) &DebugEvent;
  4544. va_list valist;
  4545. if ( pEntry->hTrace == NULL )
  4546. {
  4547. return; // NOP
  4548. } // if: no trace logger
  4549. if ( bLogLevelIn > pEntry->bLevel )
  4550. {
  4551. return; // NOP
  4552. } // if: level no high enough
  4553. ZeroMemory( &DebugEvent, sizeof( DebugEvent ) );
  4554. #ifndef UNICODE
  4555. TCHAR szFormat[ cchDEBUG_OUTPUT_BUFFER_SIZE ];
  4556. wcstombs( szFormat, pszFormatIn, StrLenW( pszFormatIn ) + 1 );
  4557. va_start( valist, pszFormatIn );
  4558. wvnsprintf( DebugEvent.szMsg, 256,szFormat, valist);
  4559. va_end( valist );
  4560. #else
  4561. va_start( valist, pszFormatIn );
  4562. wvnsprintf( DebugEvent.szMsg, 256,pszFormatIn, valist);
  4563. va_end( valist );
  4564. #endif // UNICODE
  4565. //
  4566. // Fill in the blanks
  4567. //
  4568. DebugEvent.bSize = (BYTE) wcslen( DebugEvent.szMsg );
  4569. peth->Size = sizeof( DebugEvent );
  4570. peth->Class.Type = 10;
  4571. peth->Class.Level = pEntry->bLevel;
  4572. // peth->Class.Version = 0;
  4573. // peth->ThreadId = GetCurrentThreadId( ); - done by system
  4574. pwnh->Guid = *pEntry->guidControl;
  4575. // peth->ClientContext = NULL;
  4576. pwnh->Flags = WNODE_FLAG_TRACED_GUID;
  4577. // GetSystemTimeAsFileTime( (FILETIME *) &peth->TimeStamp ); - done by the system
  4578. ulStatus = TraceEvent( pEntry->hTrace, (PEVENT_TRACE_HEADER) &DebugEvent );
  4579. } //*** WMIMessageByLevel( )