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.

887 lines
19 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("RIPREP")
  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. OutputDebugStringA( "| " );
  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. if ( hr )
  432. {
  433. TCHAR szBuf[ DEBUG_OUTPUT_BUFFER_SIZE ];
  434. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  435. LPTSTR pszMsgBuf;
  436. switch ( hr )
  437. {
  438. case S_FALSE:
  439. pszMsgBuf = TEXT("S_FALSE\n");
  440. break;
  441. default:
  442. FormatMessage(
  443. FORMAT_MESSAGE_ALLOCATE_BUFFER
  444. | FORMAT_MESSAGE_FROM_SYSTEM,
  445. NULL,
  446. hr,
  447. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  448. (LPTSTR)&pszMsgBuf,
  449. 0,
  450. NULL
  451. );
  452. }
  453. // Make sure everything is cool before we blow up somewhere else.
  454. if ( pszMsgBuf == NULL )
  455. {
  456. pszMsgBuf = TEXT("<unknown error code returned>\n");
  457. }
  458. Assert( pszFile != NULL );
  459. Assert( pszModule != NULL );
  460. Assert( pszfn != NULL );
  461. dbgmakefilelinestring( szFileLine, pszFile, uLine );
  462. wsprintf( szBuf, TEXT("%-50s %-10s HRESULT: hr = 0x%08x - %s"),
  463. szFileLine, pszModule, hr, pszMsgBuf );
  464. dbgEnterCS( );
  465. OutputDebugString( szBuf );
  466. dbgExitCS( );
  467. 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?"),
  468. pszModule, uLine, pszFile, pszfn, hr, pszMsgBuf );
  469. if ( IDYES == MessageBox( NULL, szBuf, TEXT("Trace HRESULT"),
  470. MB_YESNO|MB_ICONWARNING ) )
  471. DEBUG_BREAK;
  472. if ( hr != S_OK && hr != S_FALSE )
  473. {
  474. LocalFree( pszMsgBuf );
  475. }
  476. }
  477. return hr;
  478. }
  479. //
  480. // Memory allocation and tracking
  481. //
  482. typedef struct _MEMORYBLOCK {
  483. HGLOBAL hglobal;
  484. DWORD dwBytes;
  485. UINT uFlags;
  486. LPCTSTR pszFile;
  487. int uLine;
  488. LPCTSTR pszModule;
  489. LPCTSTR pszComment;
  490. _MEMORYBLOCK *pNext;
  491. } MEMORYBLOCK, *LPMEMORYBLOCK;
  492. //
  493. // Adds a MEMORYBLOCK to the memory tracking list.
  494. //
  495. HGLOBAL
  496. DebugMemoryAdd(
  497. HGLOBAL hglobal,
  498. LPCTSTR pszFile,
  499. const int uLine,
  500. LPCTSTR pszModule,
  501. UINT uFlags,
  502. DWORD dwBytes,
  503. LPCTSTR pszComment )
  504. {
  505. if ( hglobal )
  506. {
  507. LPMEMORYBLOCK pmbHead = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  508. LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) GlobalAlloc(
  509. GMEM_FIXED,
  510. sizeof(MEMORYBLOCK) );
  511. if ( !pmb )
  512. {
  513. GlobalFree( hglobal );
  514. return NULL;
  515. }
  516. pmb->hglobal = hglobal;
  517. pmb->dwBytes = dwBytes;
  518. pmb->uFlags = uFlags;
  519. pmb->pszFile = pszFile;
  520. pmb->uLine = uLine;
  521. pmb->pszModule = pszModule;
  522. pmb->pszComment = pszComment;
  523. pmb->pNext = pmbHead;
  524. TlsSetValue( g_TraceMemoryIndex, pmb );
  525. TraceMessage( pmb->pszFile,
  526. pmb->uLine,
  527. pmb->pszModule,
  528. TF_MEMORYALLOCS,
  529. L"Alloced %s - %u bytes at 0x%08x (pmb=0x%08x)\n",
  530. pszComment,
  531. dwBytes,
  532. pmb->hglobal,
  533. pmb );
  534. }
  535. return hglobal;
  536. }
  537. //
  538. // Removes a MEMORYBLOCK to the memory tracking list.
  539. //
  540. void
  541. DebugMemoryDelete(
  542. HGLOBAL hglobal )
  543. {
  544. if ( hglobal )
  545. {
  546. LPMEMORYBLOCK pmbHead = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  547. LPMEMORYBLOCK pmbLast = NULL;
  548. while ( pmbHead && pmbHead->hglobal != hglobal )
  549. {
  550. pmbLast = pmbHead;
  551. pmbHead = pmbLast->pNext;
  552. }
  553. if ( pmbHead )
  554. {
  555. if ( pmbLast )
  556. {
  557. pmbLast->pNext = pmbHead->pNext;
  558. }
  559. else
  560. {
  561. TlsSetValue( g_TraceMemoryIndex, pmbHead->pNext );
  562. }
  563. TraceMessage( pmbHead->pszFile,
  564. pmbHead->uLine,
  565. pmbHead->pszModule,
  566. TF_MEMORYALLOCS,
  567. L"Freeing %s - %u bytes from 0x%08x (pmb=0x%08x)\n",
  568. pmbHead->pszComment,
  569. pmbHead->dwBytes,
  570. pmbHead->hglobal,
  571. pmbHead );
  572. memset( pmbHead->hglobal, 0xFA, pmbHead->dwBytes );
  573. memset( pmbHead, 0xFE, sizeof(*pmbHead) );
  574. GlobalFree( pmbHead );
  575. }
  576. else
  577. {
  578. #if 0
  579. DebugMsg( "\n**** Attempted to free memory at 0x%08x (ThreadID = 0x%08x) ****\n\n",
  580. hglobal, GetCurrentThreadId( ) );
  581. #endif
  582. }
  583. }
  584. }
  585. //
  586. // Allocates memory and adds the MEMORYBLOCK to the memory tracking list.
  587. //
  588. HGLOBAL
  589. DebugAlloc(
  590. LPCTSTR pszFile,
  591. const int uLine,
  592. LPCTSTR pszModule,
  593. UINT uFlags,
  594. DWORD dwBytes,
  595. LPCTSTR pszComment )
  596. {
  597. HGLOBAL hglobal = GlobalAlloc( uFlags, dwBytes );
  598. return DebugMemoryAdd( hglobal, pszFile, uLine, pszModule, uFlags, dwBytes, pszComment );
  599. }
  600. //
  601. // Remove the MEMORYBLOCK to the memory tracking list, memsets the
  602. // memory to 0xFE and then frees the memory.
  603. //
  604. HGLOBAL
  605. DebugFree(
  606. HGLOBAL hglobal )
  607. {
  608. DebugMemoryDelete( hglobal );
  609. return GlobalFree( hglobal );
  610. }
  611. //
  612. // Checks the memory tracking list. If it is not empty, it will dump the
  613. // list and break.
  614. //
  615. void
  616. DebugMemoryCheck( )
  617. {
  618. BOOL fFoundLeak = FALSE;
  619. LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) TlsGetValue( g_TraceMemoryIndex );
  620. dbgEnterCS( );
  621. while ( pmb )
  622. {
  623. LPVOID args[ 5 ];
  624. TCHAR szOutput[ DEBUG_OUTPUT_BUFFER_SIZE ];
  625. TCHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  626. if ( fFoundLeak == FALSE )
  627. {
  628. DebugMsg("\n******** Memory leak detected ******** ThreadID = 0x%08x ******** \n\n", GetCurrentThreadId( ) );
  629. //OutputDebugString("12345678901234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1...");
  630. OutputDebugString(TEXT("Filename(Line Number): Module Addr/HGLOBAL Size String\n"));
  631. fFoundLeak = TRUE;
  632. }
  633. dbgmakefilelinestring( szFileLine, pmb->pszFile, pmb->uLine );
  634. args[0] = (LPVOID) pmb->hglobal;
  635. args[1] = (LPVOID) &szFileLine;
  636. args[2] = (LPVOID) pmb->pszComment;
  637. args[3] = UlongToPtr(pmb->dwBytes);
  638. args[4] = (LPVOID) pmb->pszModule;
  639. if ( !!(pmb->uFlags & GMEM_MOVEABLE) )
  640. {
  641. FormatMessage(
  642. FORMAT_MESSAGE_FROM_STRING |
  643. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  644. TEXT("%2!-50s! %5!-10s! H 0x%1!08x! %4!-5u! \"%3\"\n"),
  645. 0, // error code
  646. 0, // default language
  647. (LPTSTR) &szOutput, // output buffer
  648. ARRAYSIZE( szOutput ), // size of buffer
  649. (va_list*) &args ); // arguments
  650. }
  651. else
  652. {
  653. FormatMessage(
  654. FORMAT_MESSAGE_FROM_STRING |
  655. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  656. TEXT("%2!-50s! %5!-10s! A 0x%1!08x! %4!-5u! \"%3\"\n"),
  657. 0, // error code
  658. 0, // default language
  659. (LPTSTR) &szOutput, // output buffer
  660. ARRAYSIZE( szOutput ), // size of buffer
  661. (va_list*) &args ); // arguments
  662. }
  663. OutputDebugString( szOutput );
  664. pmb = pmb->pNext;
  665. }
  666. if ( fFoundLeak == TRUE )
  667. {
  668. OutputDebugString(TEXT("\n***************************** Memory leak detected *****************************\n\n"));
  669. }
  670. dbgExitCS( );
  671. Assert( !fFoundLeak );
  672. }
  673. //
  674. // Global Management Functions -
  675. //
  676. // These are in debug and retail but internally they change
  677. // depending on the build.
  678. //
  679. #undef new
  680. void* __cdecl operator new( size_t nSize, LPCTSTR pszFile, const int iLine, LPCTSTR pszModule )
  681. {
  682. return DebugAlloc( pszFile, iLine, pszModule, GPTR, nSize, TEXT("new()") );
  683. }
  684. void * __cdecl operator new(size_t t_size )
  685. {
  686. AssertMsg( 0, "Macro failure" );
  687. return NULL;
  688. }
  689. void __cdecl operator delete(void *pv)
  690. {
  691. TraceFree( pv );
  692. }
  693. int __cdecl _purecall(void)
  694. {
  695. return 0;
  696. }
  697. #else // ! DEBUG -- It's retail
  698. //
  699. // Global Management Functions -
  700. //
  701. // These are in debug and retail but are internally they change
  702. // depending on the build.
  703. //
  704. void * __cdecl operator new(size_t t_size )
  705. {
  706. return LocalAlloc( GPTR, t_size );
  707. }
  708. void __cdecl operator delete(void *pv)
  709. {
  710. LocalFree( pv );
  711. }
  712. int __cdecl _purecall(void)
  713. {
  714. return 0;
  715. }
  716. #endif // DEBUG