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.

5217 lines
144 KiB

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