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.

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