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.

907 lines
20 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. File: DEBUG.CPP
  5. Debugging utilities
  6. ***************************************************************************/
  7. #include "pch.h"
  8. #include <shlwapi.h>
  9. DEFINE_MODULE("IMADMUI")
  10. #ifdef DEBUG
  11. // Constants
  12. #define DEBUG_OUTPUT_BUFFER_SIZE 512
  13. // Globals
  14. DWORD g_TraceMemoryIndex = 0;
  15. DWORD g_dwCounter = 0;
  16. DWORD g_dwTraceFlags = 0;
  17. CRITICAL_SECTION g_DebugCS;
  18. BOOL g_fDebugInitialized = FALSE;
  19. // Statics
  20. static const TCHAR g_szNULL[] = TEXT("");
  21. static const TCHAR g_szTrue[] = TEXT("True");
  22. static const TCHAR g_szFalse[] = TEXT("False");
  23. static const TCHAR g_szFormat[] = TEXT("%-50s %-10.10s ");
  24. static const TCHAR g_szUnknown[] = TEXT("<unknown>");
  25. //
  26. // DebugInitializeTraceFlags( )
  27. //
  28. void
  29. DebugInitializeTraceFlags( )
  30. {
  31. TCHAR szPath[ MAX_PATH ];
  32. LPTSTR pszExtension;
  33. GetModuleFileName( g_hInstance, szPath, ARRAYSIZE( szPath ) );
  34. pszExtension = &szPath[ lstrlen( szPath ) - 3 ];
  35. StrCpy( pszExtension, TEXT("ini") );
  36. DebugMsg( "Reading %s for debug settings...\n", szPath );
  37. g_dwTraceFlags = GetPrivateProfileInt( __MODULE__, TEXT("TraceFlags"), 0, szPath );
  38. DebugMsg( "g_dwTraceFlags = 0x%08x\n", g_dwTraceFlags );
  39. }
  40. //
  41. // Debugging strrchr( )
  42. //
  43. LPCTSTR
  44. dbgstrrchr( LPCTSTR lpsz, char ch )
  45. {
  46. LPCTSTR psz = lpsz;
  47. while ( *psz )
  48. ++psz;
  49. while ( psz >= lpsz && *psz != ch )
  50. --psz;
  51. return psz;
  52. }
  53. //
  54. // Adds 'g_dwCounter' spaces to debug spew
  55. //
  56. void
  57. dbgspace( void )
  58. {
  59. for( DWORD dw = 1; dw < g_dwCounter; dw++ )
  60. OutputDebugStringA( "| " );
  61. }
  62. //
  63. // Makes sure multiple threads don't trample debugging output.
  64. //
  65. void
  66. dbgEnterCS( void )
  67. {
  68. if ( !g_fDebugInitialized )
  69. {
  70. //
  71. // There is NO matching DeleteCriticalSection( ) since
  72. // this is only used for debugging purposes.
  73. //
  74. InitializeCriticalSection( &g_DebugCS );
  75. g_fDebugInitialized = TRUE;
  76. }
  77. EnterCriticalSection( &g_DebugCS );
  78. }
  79. void
  80. dbgExitCS( void )
  81. {
  82. LeaveCriticalSection( &g_DebugCS );
  83. }
  84. //
  85. // Takes the filename and line number and put them into a string buffer.
  86. //
  87. // NOTE: the buffer is assumed to be of size DEBUG_OUTPUT_BUFFER_SIZE.
  88. //
  89. LPTSTR
  90. dbgmakefilelinestring(
  91. LPTSTR pszBuf,
  92. LPCTSTR pszFile,
  93. const int uLine )
  94. {
  95. LPVOID args[2];
  96. args[0] = (LPVOID) pszFile;
  97. args[1] = IntToPtr(uLine);
  98. FormatMessage(
  99. FORMAT_MESSAGE_FROM_STRING |
  100. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  101. TEXT("%1(%2!u!):"),
  102. 0, // error code
  103. 0, // default language
  104. (LPTSTR) pszBuf, // output buffer
  105. DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
  106. (va_list*) &args ); // arguments
  107. return pszBuf;
  108. }
  109. //
  110. // TraceMsg() - ascii
  111. //
  112. void
  113. TraceMsg(
  114. DWORD dwCheckFlags,
  115. LPCSTR pszFormat,
  116. ... )
  117. {
  118. va_list valist;
  119. if (( dwCheckFlags == TF_ALWAYS
  120. || !!( g_dwTraceFlags & dwCheckFlags ) ))
  121. {
  122. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  123. #ifdef UNICODE
  124. TCHAR szFormat[ DEBUG_OUTPUT_BUFFER_SIZE ];
  125. mbstowcs( szFormat, pszFormat, lstrlenA( pszFormat ) + 1 );
  126. va_start( valist, pszFormat );
  127. wvsprintf( szBuf, szFormat, valist );
  128. va_end( valist );
  129. #else
  130. va_start( valist, pszFormat );
  131. wvsprintf( szBuf, pszFormat, valist );
  132. va_end( valist );
  133. #endif // UNICODE
  134. dbgEnterCS( );
  135. OutputDebugString( szBuf );
  136. dbgExitCS( );
  137. }
  138. }
  139. //
  140. // TraceMsg() - unicode
  141. //
  142. void
  143. TraceMsg(
  144. DWORD dwCheckFlags,
  145. LPCWSTR pszFormat,
  146. ... )
  147. {
  148. va_list valist;
  149. if (( dwCheckFlags == TF_ALWAYS
  150. || !!( g_dwTraceFlags & dwCheckFlags ) ))
  151. {
  152. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  153. #ifndef UNICODE
  154. TCHAR szFormat[ DEBUG_OUTPUT_BUFFER_SIZE ];
  155. wcstombs( szFormat, pszFormat, lstrlenW( pszFormat ) + 1 );
  156. va_start( valist, pszFormat );
  157. wvsprintf( szBuf, szFormat, valist);
  158. va_end( valist );
  159. #else
  160. va_start( valist, pszFormat );
  161. wvsprintf( szBuf, pszFormat, valist);
  162. va_end( valist );
  163. #endif // UNICODE
  164. dbgEnterCS( );
  165. OutputDebugStringW( szBuf );
  166. dbgExitCS( );
  167. }
  168. }
  169. //
  170. // TraceMessage()
  171. //
  172. void
  173. TraceMessage(
  174. LPCTSTR pszFile,
  175. const int uLine,
  176. LPCTSTR pszModule,
  177. DWORD dwCheckFlags,
  178. LPCTSTR pszFormat,
  179. ... )
  180. {
  181. va_list valist;
  182. if (( dwCheckFlags == TF_ALWAYS
  183. || !!( g_dwTraceFlags & dwCheckFlags ) ))
  184. {
  185. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  186. if ( !pszModule )
  187. {
  188. pszModule = g_szUnknown;
  189. }
  190. if ( !pszFile )
  191. {
  192. wsprintf( szBuf, g_szFormat, g_szNULL, pszModule );
  193. }
  194. else
  195. {
  196. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  197. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  198. wsprintf( szBuf, g_szFormat, szFileLine, pszModule );
  199. }
  200. dbgEnterCS( );
  201. OutputDebugString( szBuf );
  202. dbgspace( );
  203. va_start( valist, pszFormat );
  204. wvsprintf( szBuf, pszFormat, valist );
  205. va_end( valist );
  206. OutputDebugString( szBuf );
  207. dbgExitCS( );
  208. }
  209. }
  210. //
  211. // TraceMessageDo()
  212. //
  213. void
  214. TraceMessageDo(
  215. LPCTSTR pszFile,
  216. const int uLine,
  217. LPCTSTR pszModule,
  218. DWORD dwCheckFlags,
  219. LPCTSTR pszFormat,
  220. LPCTSTR pszFunc,
  221. ... )
  222. {
  223. va_list valist;
  224. if (( dwCheckFlags == TF_ALWAYS
  225. || !!( g_dwTraceFlags & dwCheckFlags ) ))
  226. {
  227. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  228. TCHAR szVar[ DEBUG_OUTPUT_BUFFER_SIZE ];
  229. LPCTSTR psz = pszFunc;
  230. if ( !pszModule )
  231. {
  232. pszModule = g_szUnknown;
  233. }
  234. if ( !pszFile )
  235. {
  236. wsprintf( szBuf, g_szFormat, g_szNULL, pszModule );
  237. }
  238. else
  239. {
  240. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  241. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  242. wsprintf( szBuf, g_szFormat, szFileLine, pszModule );
  243. }
  244. dbgEnterCS( );
  245. OutputDebugString( szBuf );
  246. dbgspace( );
  247. while ( *psz && *psz != TEXT('='))
  248. psz++;
  249. lstrcpyn( szVar, pszFunc, (size_t)(1 + psz - pszFunc) );
  250. wsprintf( szBuf, TEXT("V %s= "), szVar );
  251. OutputDebugString( szBuf );
  252. va_start( valist, pszFunc );
  253. wvsprintf( szBuf, pszFormat, valist );
  254. va_end( valist );
  255. OutputDebugString( szBuf );
  256. OutputDebugString( TEXT("\n") );
  257. dbgExitCS( );
  258. }
  259. }
  260. //
  261. // DebugMessage()
  262. //
  263. void
  264. DebugMessage(
  265. LPCTSTR pszFile,
  266. const int uLine,
  267. LPCTSTR pszModule,
  268. LPCTSTR pszFormat,
  269. ... )
  270. {
  271. va_list valist;
  272. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  273. if ( !pszModule )
  274. {
  275. pszModule = g_szUnknown;
  276. }
  277. if ( !pszFile )
  278. {
  279. wsprintf( szBuf, g_szFormat, g_szNULL, pszModule );
  280. }
  281. else
  282. {
  283. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  284. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  285. wsprintf( szBuf, g_szFormat, szFileLine, pszModule );
  286. }
  287. dbgEnterCS( );
  288. OutputDebugString( szBuf );
  289. dbgspace( );
  290. va_start( valist, pszFormat );
  291. wvsprintf( szBuf, pszFormat, valist );
  292. va_end( valist );
  293. OutputDebugString( szBuf );
  294. dbgExitCS( );
  295. }
  296. //
  297. // DebugMessageDo()
  298. //
  299. void
  300. DebugMessageDo(
  301. LPCTSTR pszFile,
  302. const int uLine,
  303. LPCTSTR pszModule,
  304. LPCTSTR pszFormat,
  305. LPCTSTR pszFunc,
  306. ... )
  307. {
  308. va_list valist;
  309. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  310. TCHAR szVar[ DEBUG_OUTPUT_BUFFER_SIZE ];
  311. LPCTSTR psz = pszFunc;
  312. if ( !pszModule )
  313. {
  314. pszModule = g_szUnknown;
  315. }
  316. if ( !pszFile )
  317. {
  318. wsprintf( szBuf, g_szFormat, g_szNULL, pszModule );
  319. }
  320. else
  321. {
  322. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  323. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  324. wsprintf( szBuf, g_szFormat, szFileLine, pszModule );
  325. }
  326. dbgEnterCS( );
  327. OutputDebugString( szBuf );
  328. dbgspace( );
  329. while ( *psz && *psz != TEXT('='))
  330. psz++;
  331. lstrcpyn( szVar, pszFunc, (size_t)(1 + psz - pszFunc) );
  332. wsprintf( szBuf, TEXT("V %s= "), szVar );
  333. OutputDebugString( szBuf );
  334. va_start( valist, pszFunc );
  335. wvsprintf( szBuf, pszFormat, valist );
  336. va_end( valist );
  337. OutputDebugString( szBuf );
  338. OutputDebugString( TEXT("\n") );
  339. dbgExitCS( );
  340. }
  341. //
  342. // DebugMsg()
  343. //
  344. void
  345. DebugMsg(
  346. LPCSTR pszFormat,
  347. ... )
  348. {
  349. va_list valist;
  350. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  351. #ifdef UNICODE
  352. TCHAR szFormat[ DEBUG_OUTPUT_BUFFER_SIZE ];
  353. mbstowcs( szFormat, pszFormat, lstrlenA( pszFormat ) + 1 );
  354. va_start( valist, pszFormat );
  355. wvsprintf( szBuf, szFormat, valist);
  356. va_end( valist );
  357. #else
  358. va_start( valist, pszFormat );
  359. wvsprintf( szBuf, pszFormat, valist);
  360. va_end( valist );
  361. #endif // UNICODE
  362. dbgEnterCS( );
  363. OutputDebugString( szBuf );
  364. dbgExitCS( );
  365. }
  366. //
  367. // DebugMsg()
  368. //
  369. void
  370. DebugMsg(
  371. LPCWSTR pszFormat,
  372. ... )
  373. {
  374. va_list valist;
  375. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  376. #ifndef UNICODE
  377. TCHAR szFormat[ DEBUG_OUTPUT_BUFFER_SIZE ];
  378. wcstombs( szFormat, pszFormat, lstrlenW( pszFormat ) + 1 );
  379. va_start( valist, pszFormat );
  380. wvsprintf( szBuf, szFormat, valist);
  381. va_end( valist );
  382. #else
  383. va_start( valist, pszFormat );
  384. wvsprintf( szBuf, pszFormat, valist);
  385. va_end( valist );
  386. #endif // UNICODE
  387. dbgEnterCS( );
  388. OutputDebugStringW( szBuf );
  389. dbgExitCS( );
  390. }
  391. //
  392. // Displays a dialog box with the failed assertion. User has the option of
  393. // breaking.
  394. //
  395. BOOL
  396. AssertMessage(
  397. LPCTSTR pszFile,
  398. const int uLine,
  399. LPCTSTR pszModule,
  400. LPCTSTR pszfn,
  401. BOOL fTrue )
  402. {
  403. if ( !fTrue )
  404. {
  405. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  406. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  407. // Make sure everything is cool before we blow up somewhere else.
  408. if ( pszFile == NULL )
  409. {
  410. pszFile = g_szNULL;
  411. }
  412. if ( pszModule == NULL )
  413. {
  414. pszModule = g_szNULL;
  415. }
  416. if ( pszfn == NULL )
  417. {
  418. pszfn = g_szNULL;
  419. }
  420. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  421. wsprintf( szBuf, TEXT("%-50s %-10s ASSERT: %s\n"),
  422. szFileLine, pszModule, pszfn );
  423. dbgEnterCS( );
  424. OutputDebugString( szBuf );
  425. dbgExitCS( );
  426. wsprintf( szBuf, TEXT("Module:\t%s\t\nLine:\t%u\t\nFile:\t%s\t\n\nAssertion:\t%s\t\n\nDo you want to break here?"),
  427. pszModule, uLine, pszFile, pszfn );
  428. if ( IDNO == MessageBox( NULL, szBuf, TEXT("Assertion Failed!"),
  429. MB_YESNO|MB_ICONWARNING ) )
  430. fTrue = !FALSE; // don't break
  431. }
  432. return !fTrue;
  433. }
  434. //
  435. // Traces HRESULT errors. A dialog will appear is there is an error
  436. // in the hr.
  437. //
  438. HRESULT
  439. TraceHR(
  440. LPCTSTR pszFile,
  441. const int uLine,
  442. LPCTSTR pszModule,
  443. LPCTSTR pszfn,
  444. HRESULT hr )
  445. {
  446. if ( hr )
  447. {
  448. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  449. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  450. LPTSTR pszMsgBuf;
  451. BOOLEAN bDelete=TRUE;
  452. switch ( hr )
  453. {
  454. case S_FALSE:
  455. pszMsgBuf = TEXT("S_FALSE\n");
  456. break;
  457. default:
  458. FormatMessage(
  459. FORMAT_MESSAGE_ALLOCATE_BUFFER
  460. | FORMAT_MESSAGE_FROM_SYSTEM,
  461. NULL,
  462. hr,
  463. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  464. (LPTSTR)&pszMsgBuf,
  465. 0,
  466. NULL
  467. );
  468. }
  469. // Make sure everything is cool before we blow up somewhere else.
  470. if ( pszMsgBuf == NULL )
  471. {
  472. pszMsgBuf = TEXT("<unknown error code returned>\n");
  473. bDelete = FALSE;
  474. }
  475. Assert( pszFile != NULL );
  476. Assert( pszModule != NULL );
  477. Assert( pszfn != NULL );
  478. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  479. wsprintf( szBuf, TEXT("%-50s %-10s HRESULT: hr = 0x%08x - %s"),
  480. szFileLine, pszModule, hr, pszMsgBuf );
  481. dbgEnterCS( );
  482. OutputDebugString( szBuf );
  483. dbgExitCS( );
  484. wsprintf( szBuf, TEXT("Module:\t%s\t\nLine:\t%u\t\nFile:\t%s\t\n\nFunction:\t%s\t\nhr =\t0x%08x - %s\t\nDo you want to break here?"),
  485. pszModule, uLine, pszFile, pszfn, hr, pszMsgBuf );
  486. if ( IDYES == MessageBox( NULL, szBuf, TEXT("Trace HRESULT"),
  487. MB_YESNO|MB_ICONWARNING ) )
  488. DEBUG_BREAK;
  489. if ( hr != S_OK && hr != S_FALSE && bDelete)
  490. {
  491. LocalFree( pszMsgBuf );
  492. }
  493. }
  494. return hr;
  495. }
  496. //
  497. // Memory allocation and tracking
  498. //
  499. typedef struct _MEMORYBLOCK {
  500. HGLOBAL hglobal;
  501. DWORD dwBytes;
  502. UINT uFlags;
  503. LPCTSTR pszFile;
  504. int uLine;
  505. LPCTSTR pszModule;
  506. LPCTSTR pszComment;
  507. _MEMORYBLOCK *pNext;
  508. } MEMORYBLOCK, *LPMEMORYBLOCK;
  509. //
  510. // Adds a MEMORYBLOCK to the memory tracking list.
  511. //
  512. HGLOBAL
  513. DebugMemoryAdd(
  514. HGLOBAL hglobal,
  515. LPCTSTR pszFile,
  516. const int uLine,
  517. LPCTSTR pszModule,
  518. UINT uFlags,
  519. DWORD dwBytes,
  520. LPCTSTR pszComment )
  521. {
  522. if ( hglobal )
  523. {
  524. LPMEMORYBLOCK pmbHead = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  525. LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) GlobalAlloc(
  526. GMEM_FIXED,
  527. sizeof(MEMORYBLOCK) );
  528. if ( !pmb )
  529. {
  530. GlobalFree( hglobal );
  531. return NULL;
  532. }
  533. pmb->hglobal = hglobal;
  534. pmb->dwBytes = dwBytes;
  535. pmb->uFlags = uFlags;
  536. pmb->pszFile = pszFile;
  537. pmb->uLine = uLine;
  538. pmb->pszModule = pszModule;
  539. pmb->pszComment = pszComment;
  540. pmb->pNext = pmbHead;
  541. TlsSetValue( g_TraceMemoryIndex, pmb );
  542. TraceMessage( pmb->pszFile,
  543. pmb->uLine,
  544. pmb->pszModule,
  545. TF_MEMORYALLOCS,
  546. L"Alloced %s - %u bytes at 0x%08x (pmb=0x%08x)\n",
  547. pszComment,
  548. dwBytes,
  549. pmb->hglobal,
  550. pmb );
  551. }
  552. return hglobal;
  553. }
  554. //
  555. // Removes a MEMORYBLOCK to the memory tracking list.
  556. //
  557. void
  558. DebugMemoryDelete(
  559. HGLOBAL hglobal )
  560. {
  561. if ( hglobal )
  562. {
  563. LPMEMORYBLOCK pmbHead = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  564. LPMEMORYBLOCK pmbLast = NULL;
  565. while ( pmbHead && pmbHead->hglobal != hglobal )
  566. {
  567. pmbLast = pmbHead;
  568. pmbHead = pmbLast->pNext;
  569. }
  570. if ( pmbHead )
  571. {
  572. if ( pmbLast )
  573. {
  574. pmbLast->pNext = pmbHead->pNext;
  575. }
  576. else
  577. {
  578. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  579. }
  580. TraceMessage( pmbHead->pszFile,
  581. pmbHead->uLine,
  582. pmbHead->pszModule,
  583. TF_MEMORYALLOCS,
  584. L"Freeing %s - %u bytes from 0x%08x (pmb=0x%08x)\n",
  585. pmbHead->pszComment,
  586. pmbHead->dwBytes,
  587. pmbHead->hglobal,
  588. pmbHead );
  589. memset( pmbHead->hglobal, 0xFA, pmbHead->dwBytes );
  590. GlobalFree( pmbHead );
  591. }
  592. else
  593. {
  594. DebugMsg( "\n**** Attempted to free memory at 0x%08x (ThreadID = 0x%08x) ****\n\n",
  595. hglobal, GetCurrentThreadId( ) );
  596. }
  597. }
  598. }
  599. //
  600. // Allocates memory and adds the MEMORYBLOCK to the memory tracking list.
  601. //
  602. HGLOBAL
  603. DebugAlloc(
  604. LPCTSTR pszFile,
  605. const int uLine,
  606. LPCTSTR pszModule,
  607. UINT uFlags,
  608. DWORD dwBytes,
  609. LPCTSTR pszComment )
  610. {
  611. HGLOBAL hglobal = GlobalAlloc( uFlags, dwBytes );
  612. return DebugMemoryAdd( hglobal, pszFile, uLine, pszModule, uFlags, dwBytes, pszComment );
  613. }
  614. //
  615. // Remove the MEMORYBLOCK to the memory tracking list, memsets the
  616. // memory to 0xFE and then frees the memory.
  617. //
  618. HGLOBAL
  619. DebugFree(
  620. HGLOBAL hglobal )
  621. {
  622. DebugMemoryDelete( hglobal );
  623. return GlobalFree( hglobal );
  624. }
  625. //
  626. // Checks the memory tracking list. If it is not empty, it will dump the
  627. // list and break.
  628. //
  629. void
  630. DebugMemoryCheck( )
  631. {
  632. BOOL fFoundLeak = FALSE;
  633. LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  634. dbgEnterCS( );
  635. while ( pmb )
  636. {
  637. LPVOID args[ 5 ];
  638. TCHAR szOutput[ DEBUG_OUTPUT_BUFFER_SIZE ];
  639. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  640. if ( fFoundLeak == FALSE )
  641. {
  642. DebugMsg("\n******** Memory leak detected ******** ThreadID = 0x%08x ******** \n\n", GetCurrentThreadId( ) );
  643. //OutputDebugString("12345678901234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1...");
  644. OutputDebugString(TEXT("Filename(Line Number): Module Addr/HGLOBAL Size String\n"));
  645. fFoundLeak = TRUE;
  646. }
  647. dbgmakefilelinestring( szFileLine, pmb->pszFile, pmb->uLine );
  648. args[0] = (LPVOID) pmb->hglobal;
  649. args[1] = (LPVOID) &szFileLine;
  650. args[2] = (LPVOID) pmb->pszComment;
  651. args[3] = UlongToPtr(pmb->dwBytes);
  652. args[4] = (LPVOID) pmb->pszModule;
  653. if ( !!(pmb->uFlags & GMEM_MOVEABLE) )
  654. {
  655. FormatMessage(
  656. FORMAT_MESSAGE_FROM_STRING |
  657. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  658. TEXT("%2!-50s! %5!-10s! H 0x%1!08x! %4!-5u! \"%3\"\n"),
  659. 0, // error code
  660. 0, // default language
  661. (LPTSTR) &szOutput, // output buffer
  662. ARRAYSIZE( szOutput ), // size of buffer
  663. (va_list*) &args ); // arguments
  664. }
  665. else
  666. {
  667. FormatMessage(
  668. FORMAT_MESSAGE_FROM_STRING |
  669. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  670. TEXT("%2!-50s! %5!-10s! A 0x%1!08x! %4!-5u! \"%3\"\n"),
  671. 0, // error code
  672. 0, // default language
  673. (LPTSTR) &szOutput, // output buffer
  674. ARRAYSIZE( szOutput ), // size of buffer
  675. (va_list*) &args ); // arguments
  676. }
  677. OutputDebugString( szOutput );
  678. pmb = pmb->pNext;
  679. }
  680. if ( fFoundLeak == TRUE )
  681. {
  682. OutputDebugString(TEXT("\n***************************** Memory leak detected *****************************\n\n"));
  683. }
  684. dbgExitCS( );
  685. if (g_dwTraceFlags & TF_MEMORYALLOCS) {
  686. Assert( !fFoundLeak );
  687. }
  688. }
  689. //
  690. // Global Management Functions -
  691. //
  692. // These are in debug and retail but internally they change
  693. // depending on the build.
  694. //
  695. #undef new
  696. void* __cdecl operator new( size_t nSize, LPCTSTR pszFile, const int iLine, LPCTSTR pszModule )
  697. {
  698. return DebugAlloc( pszFile, iLine, pszModule, GPTR, nSize, TEXT("new()") );
  699. }
  700. void * __cdecl operator new(size_t t_size )
  701. {
  702. AssertMsg( 0, "Macro failure" );
  703. return NULL;
  704. }
  705. void __cdecl operator delete(void *pv)
  706. {
  707. TraceFree( pv );
  708. }
  709. int __cdecl _purecall(void)
  710. {
  711. return 0;
  712. }
  713. #else // ! DEBUG -- It's retail
  714. //
  715. // Global Management Functions -
  716. //
  717. // These are in debug and retail but are internally they change
  718. // depending on the build.
  719. //
  720. void * __cdecl operator new(size_t t_size )
  721. {
  722. return LocalAlloc( GPTR, t_size );
  723. }
  724. void __cdecl operator delete(void *pv)
  725. {
  726. LocalFree( pv );
  727. }
  728. int __cdecl _purecall(void)
  729. {
  730. return 0;
  731. }
  732. #endif // DEBUG