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.

1787 lines
44 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: OSInd.cpp
  6. * Content: OS indirection functions to abstract OS specific items.
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/12/99 jtk Created
  12. * 09/21/99 rodtoll Fixed for retail builds
  13. * 09/22/99 jtk Added callstacks to memory allocations
  14. * 08/28/2000 masonb Voice Merge: Allow new and delete with size of 0
  15. * 11/28/2000 rodtoll: WinBug #206257 - Retail DPNET.DLL links to DebugBreak()
  16. * 12/22/2000 aarono: ManBug # 190380 use process heap for retail.
  17. ***************************************************************************/
  18. #include "dncmni.h"
  19. #define PROF_SECT "DirectPlay8"
  20. //**********************************************************************
  21. // Constant definitions
  22. //**********************************************************************
  23. //
  24. // CRC key for validating memory linkages
  25. // Signature for validating memory blocks
  26. //
  27. #ifdef _WIN64
  28. #define MEMORY_CRC 0X5AA55AA55AA55AA5
  29. #define GUARD_SIGNATURE 0x0F1E2D3C4B5A6978
  30. #else
  31. #define MEMORY_CRC 0X5AA55AA5
  32. #define GUARD_SIGNATURE 0x0F1E2D3C
  33. #endif // _WIN64
  34. static CRITICAL_SECTION g_AllocatedMemoryLock;
  35. //
  36. // signature for validating memory blocks
  37. //
  38. //
  39. // enumerated values to indicate how to report memory leaks
  40. //
  41. #if defined( DN_MEMORY_TRACKING ) || defined( DN_CRITICAL_SECTION_TRACKING )
  42. #define MEMORY_LEAK_REPORT_NONE 0x00000000
  43. #define MEMORY_LEAK_REPORT_DPF 0x00000001
  44. #define MEMORY_LEAK_REPORT_DIALOG 0x00000002
  45. #endif
  46. //**********************************************************************
  47. // Macro definitions
  48. //**********************************************************************
  49. //
  50. // Macro to compute the offset of an element inside of a larger structure.
  51. // Copied from MSDEV's STDLIB.H and modified to return INT_PTR
  52. //
  53. #define OFFSETOF(s,m) ( ( INT_PTR ) &( ( (s*) 0 )->m ) )
  54. //
  55. // macro for length of array
  56. //
  57. #define LENGTHOF( arg ) ( sizeof( arg ) / sizeof( arg[ 0 ] ) )
  58. //
  59. // ASSERT macro
  60. //
  61. #ifdef _DEBUG
  62. #ifdef _X86_
  63. #define ASSERT( arg ) if ( arg == FALSE ) { _asm { int 3 }; }
  64. #else
  65. #define ASSERT( arg ) if ( arg == FALSE ) { DebugBreak(); }
  66. #endif
  67. #else // _DEBUG
  68. #define ASSERT( arg )
  69. #endif //_DEBUG
  70. //**********************************************************************
  71. // Structure definitions
  72. //**********************************************************************
  73. //**********************************************************************
  74. // Variable definitions
  75. //**********************************************************************
  76. //
  77. // debug variable to make sure we're initialized before having any functions
  78. // called
  79. //
  80. DEBUG_ONLY( static BOOL g_fOSIndirectionLayerInitialized = FALSE );
  81. //
  82. // time variables
  83. //
  84. static DNCRITICAL_SECTION g_TimeLock;
  85. static DWORD g_dwLastTimeCall = 0;
  86. #ifdef DN_CRITICAL_SECTION_TRACKING
  87. CBilink g_blCritSecs;
  88. DNCRITICAL_SECTION g_CSLock;
  89. #endif
  90. #ifdef DN_MEMORY_TRACKING
  91. DWORD g_dwMemLeakDisplayFlags = MEMORY_LEAK_REPORT_DPF;
  92. #endif
  93. //
  94. // OS items
  95. //
  96. static OSVERSIONINFO g_OSVersionInfo;
  97. static HINSTANCE g_hApplicationInstance;
  98. //
  99. // memory heap
  100. //
  101. HANDLE g_hMemoryHeap = NULL;
  102. PSECURITY_ATTRIBUTES g_psa = NULL;
  103. SECURITY_ATTRIBUTES g_sa;
  104. BYTE g_pSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
  105. BOOL g_fDaclInited = FALSE;
  106. //**********************************************************************
  107. // Function prototypes
  108. //**********************************************************************
  109. #ifdef DN_MEMORY_TRACKING
  110. static int DisplayMemoryLeaks( void );
  111. BOOL DNMemoryTrackInitialize( void );
  112. #endif
  113. #if defined( DN_MEMORY_TRACKING ) || defined( DN_CRITICAL_SECTION_TRACKING )
  114. static int DisplayCallStack( const char *const pszMsg,
  115. const char *const pszTitle,
  116. const char *const pCallStack );
  117. #endif
  118. //**********************************************************************
  119. // Function definitions
  120. //**********************************************************************
  121. typedef BOOL (WINAPI *PFNINITCRITSECANDSPINCOUNT)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
  122. PFNINITCRITSECANDSPINCOUNT g_pfnInitializeCriticalSectionAndSpinCount = NULL;
  123. //**********************************************************************
  124. // ------------------------------
  125. // DNOSIndirectionInit - initialize the OS indirection layer
  126. //
  127. // Entry: Nothing
  128. //
  129. // Exit: Boolean indicating success
  130. // TRUE = initialization successful
  131. // FALSE = initialization unsuccessful
  132. // ------------------------------
  133. #undef DPF_MODNAME
  134. #define DPF_MODNAME "DNOSIndirectionInit"
  135. BOOL DNOSIndirectionInit( void )
  136. {
  137. BOOL fReturn;
  138. DNASSERT( g_fOSIndirectionLayerInitialized == FALSE );
  139. //
  140. // initialize
  141. //
  142. fReturn = TRUE;
  143. //
  144. // note OS version
  145. //
  146. memset( &g_OSVersionInfo, 0x00, sizeof( g_OSVersionInfo ) );
  147. g_OSVersionInfo.dwOSVersionInfoSize = sizeof( g_OSVersionInfo );
  148. if ( GetVersionEx( &g_OSVersionInfo ) == FALSE )
  149. {
  150. return FALSE;
  151. }
  152. HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
  153. if (hKernel32 != NULL)
  154. {
  155. g_pfnInitializeCriticalSectionAndSpinCount = (PFNINITCRITSECANDSPINCOUNT) GetProcAddress(hKernel32, "InitializeCriticalSectionAndSpinCount");
  156. }
  157. //
  158. // note application instance
  159. //
  160. g_hApplicationInstance = GetModuleHandle( NULL );
  161. if ( g_hApplicationInstance == NULL )
  162. {
  163. DWORD dwError;
  164. dwError = GetLastError();
  165. DPFX(DPFPREP, 0, "Failed to GetModuleHandle: 0x%x", dwError );
  166. goto Failure;
  167. }
  168. #ifdef DN_MEMORY_TRACKING
  169. g_dwMemLeakDisplayFlags = GetProfileIntA( PROF_SECT, "MemoryLeakOutput", MEMORY_LEAK_REPORT_DPF );
  170. #endif
  171. //
  172. // intialize critical section tracking code before anything else!
  173. //
  174. #ifdef DN_CRITICAL_SECTION_TRACKING
  175. g_blCritSecs.Initialize();
  176. if ( DNInitializeCriticalSection(&g_CSLock) == FALSE )
  177. {
  178. DPFX(DPFPREP, 0, "Failed to initialize critical section tracking code!" );
  179. DNASSERT( FALSE );
  180. goto Failure;
  181. }
  182. #endif // DN_CRITICAL_SECTION_TRACKING
  183. //
  184. // intiailize memory tracking before creating new memory heap
  185. //
  186. #ifdef DN_MEMORY_TRACKING
  187. if ( DNMemoryTrackInitialize() == FALSE )
  188. {
  189. DPFX(DPFPREP, 0, "Failed to initialize memory tracking code!" );
  190. DNASSERT( FALSE );
  191. goto Failure;
  192. }
  193. #endif // DN_MEMORY_TRACKING
  194. DNASSERT( g_hMemoryHeap == NULL );
  195. #ifdef _DEBUG
  196. g_hMemoryHeap = HeapCreate( 0, // flags (none)
  197. 0, // initial size (default)
  198. 0 // maximum heap size (allow heap to grow)
  199. );
  200. #else
  201. g_hMemoryHeap = GetProcessHeap();
  202. #endif
  203. if ( g_hMemoryHeap == NULL )
  204. {
  205. DPFX(DPFPREP, 0, "Failed to create memory heap!" );
  206. goto Failure;
  207. }
  208. //
  209. // get initial time for timebase
  210. //
  211. g_dwLastTimeCall = GETTIMESTAMP();
  212. if ( DNInitializeCriticalSection( &g_TimeLock ) == FALSE )
  213. {
  214. goto Failure;
  215. }
  216. goto Exit;
  217. Exit:
  218. if ( fReturn != FALSE )
  219. {
  220. DEBUG_ONLY( g_fOSIndirectionLayerInitialized = TRUE );
  221. }
  222. return fReturn;
  223. Failure:
  224. fReturn = FALSE;
  225. DNOSIndirectionDeinit();
  226. goto Exit;
  227. }
  228. //**********************************************************************
  229. //**********************************************************************
  230. // ------------------------------
  231. // DNOSIndirectionDeinit - deinitialize OS indirection layer
  232. //
  233. // Entry: Nothing
  234. //
  235. // Exit: Nothing
  236. // ------------------------------
  237. #undef DPF_MODNAME
  238. #define DPF_MODNAME "DNOSIndirectionDeinit"
  239. void DNOSIndirectionDeinit( void )
  240. {
  241. //
  242. // clean up time management resources
  243. //
  244. DNDeleteCriticalSection( &g_TimeLock );
  245. #ifdef DN_CRITICAL_SECTION_TRACKING
  246. //
  247. // Display CritSec leaks before displaying memory leaks, because displaying memory leaks
  248. // may free the memory for the CritSec and corrupt the CritSec bilink
  249. //
  250. BOOL fDisplayLeaks = TRUE;
  251. DNEnterCriticalSection(&g_CSLock);
  252. CBilink* pblCS = g_blCritSecs.GetNext();
  253. while (pblCS != &g_blCritSecs)
  254. {
  255. UINT_PTR MessageReturn;
  256. char CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
  257. char LeakSizeString[ 50 ];
  258. char DialogTitle[ 1000 ];
  259. DNCRITICAL_SECTION* pCS = CONTAINING_RECORD(pblCS, DNCRITICAL_SECTION, blCritSec);
  260. #ifdef _IA64_
  261. wsprintf( LeakSizeString, "Critical Section leaked at address 0x%p!\n", pCS );
  262. #else
  263. wsprintf( LeakSizeString, "Critical Section leaked at address 0x%08x!\n", pCS );
  264. #endif
  265. strcpy( DialogTitle, "DirectPlay8 critical section leak detected!");
  266. pCS->AllocCallStack.GetCallStackString( CallStackBuffer );
  267. if ( ( g_dwMemLeakDisplayFlags & MEMORY_LEAK_REPORT_DPF ) != 0 )
  268. {
  269. DPFX(DPFPREP, 0, "%s%s%s\n", DialogTitle, LeakSizeString, CallStackBuffer );
  270. }
  271. if ( ( g_dwMemLeakDisplayFlags & MEMORY_LEAK_REPORT_DIALOG ) != 0 )
  272. {
  273. if ( fDisplayLeaks != FALSE )
  274. {
  275. MessageReturn = DisplayCallStack( LeakSizeString, DialogTitle, CallStackBuffer );
  276. switch ( MessageReturn )
  277. {
  278. //
  279. // stop application now
  280. //
  281. case IDABORT:
  282. {
  283. fDisplayLeaks = FALSE;
  284. break;
  285. }
  286. //
  287. // display next leak
  288. //
  289. case IDIGNORE:
  290. {
  291. break;
  292. }
  293. //
  294. // stop in the debugger
  295. //
  296. case IDRETRY:
  297. {
  298. DNASSERT( FALSE );
  299. break;
  300. }
  301. //
  302. // unknown
  303. //
  304. default:
  305. {
  306. DNASSERT( FALSE );
  307. break;
  308. }
  309. }
  310. }
  311. }
  312. pblCS = pblCS->GetNext();
  313. }
  314. DNLeaveCriticalSection(&g_CSLock);
  315. DNDeleteCriticalSection( &g_CSLock );
  316. #endif // DN_CRITICAL_SECTION_TRACKING
  317. //
  318. // Report memory leaks, validate the heap if we're on NT and then destroy
  319. // the heap.
  320. //
  321. if ( g_hMemoryHeap != NULL )
  322. {
  323. //
  324. // report memory leaks, if applicable
  325. //
  326. #ifdef DN_MEMORY_TRACKING
  327. DNMemoryTrackDisplayMemoryLeaks();
  328. DeleteCriticalSection( &g_AllocatedMemoryLock );
  329. #endif // DN_MEMORY_TRACKING
  330. //
  331. // Validate heap contents before shutdown. This code only works on NT.
  332. //
  333. #ifdef _DEBUG
  334. if ( DNGetOSType() == VER_PLATFORM_WIN32_NT)
  335. {
  336. //
  337. // Check heap
  338. //
  339. if ( HeapValidate( g_hMemoryHeap, 0, NULL ) == FALSE )
  340. {
  341. DPFX(DPFPREP, 0, "Problem validating heap on destroy!" );
  342. }
  343. }
  344. //
  345. // destroy heap - debug only, we use the process heap for retail.
  346. //
  347. if ( HeapDestroy( g_hMemoryHeap ) == FALSE )
  348. {
  349. DWORD dwErrorReturn;
  350. dwErrorReturn = GetLastError();
  351. DPFX(DPFPREP, 0, "Problem destroying heap in DNOSIndirectionDeinit!" );
  352. DisplayErrorCode( 0, dwErrorReturn );
  353. }
  354. #endif _DEBUG
  355. g_hMemoryHeap = NULL;
  356. }
  357. //
  358. // clean critical section management resources
  359. //
  360. DEBUG_ONLY( g_fOSIndirectionLayerInitialized = FALSE );
  361. }
  362. //**********************************************************************
  363. //**********************************************************************
  364. // ------------------------------
  365. // DNGetOSType - get OS type
  366. //
  367. // Entry: Nothing
  368. //
  369. // Exit: OS type
  370. // ------------------------------
  371. #undef DPF_MODNAME
  372. #define DPF_MODNAME "DNGetOSType"
  373. UINT_PTR DNGetOSType( void )
  374. {
  375. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  376. return g_OSVersionInfo.dwPlatformId;
  377. }
  378. //**********************************************************************
  379. // ------------------------------
  380. // DNOSIsXPOrGreater - return TRUE if OS is WindowsXP or later or NT flavor
  381. //
  382. // Entry: Nothing
  383. //
  384. // Exit: BOOL
  385. // ------------------------------
  386. #undef DPF_MODNAME
  387. #define DPF_MODNAME "DNOSIsXPOrGreater"
  388. BOOL DNOSIsXPOrGreater( void )
  389. {
  390. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  391. return ((g_OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  392. ((g_OSVersionInfo.dwMajorVersion > 5) || ((g_OSVersionInfo.dwMajorVersion == 5) && (g_OSVersionInfo.dwMinorVersion >= 1)))
  393. );
  394. }
  395. //**********************************************************************
  396. //**********************************************************************
  397. // ------------------------------
  398. // DNGetNullDacl - get a SECURITY_ATTRIBUTE structure that specifies a
  399. // NULL DACL which is accesible by all users.
  400. //
  401. // Entry: Nothing
  402. //
  403. // Exit: PSECURITY_ATTRIBUTES
  404. // ------------------------------
  405. #undef DPF_MODNAME
  406. #define DPF_MODNAME "DNGetNullDacl"
  407. PSECURITY_ATTRIBUTES DNGetNullDacl()
  408. {
  409. // This is done to make this function independent of DNOSIndirectionInit so that the debug
  410. // layer can call it before the indirection layer is initialized.
  411. if (!g_fDaclInited)
  412. {
  413. if (!InitializeSecurityDescriptor((SECURITY_DESCRIPTOR*)g_pSD, SECURITY_DESCRIPTOR_REVISION))
  414. {
  415. DPFX(DPFPREP, 0, "Failed to initialize security descriptor" );
  416. }
  417. else
  418. {
  419. // Add a NULL DACL to the security descriptor..
  420. if (!SetSecurityDescriptorDacl((SECURITY_DESCRIPTOR*)g_pSD, TRUE, (PACL) NULL, FALSE))
  421. {
  422. DPFX(DPFPREP, 0, "Failed to set NULL DACL on security descriptor" );
  423. }
  424. else
  425. {
  426. g_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  427. g_sa.lpSecurityDescriptor = g_pSD;
  428. g_sa.bInheritHandle = FALSE;
  429. g_psa = &g_sa;
  430. }
  431. }
  432. g_fDaclInited = TRUE;
  433. }
  434. return g_psa;
  435. }
  436. //**********************************************************************
  437. //**********************************************************************
  438. // ------------------------------
  439. // DNGetApplcationInstance - application instance
  440. //
  441. // Entry: Nothing
  442. //
  443. // Exit: Application instance
  444. // ------------------------------
  445. #undef DPF_MODNAME
  446. #define DPF_MODNAME "DNGetApplicationInstance"
  447. HINSTANCE DNGetApplicationInstance( void )
  448. {
  449. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  450. return g_hApplicationInstance;
  451. }
  452. //**********************************************************************
  453. //**********************************************************************
  454. // ------------------------------
  455. // DNTimeGet - get time in milliseconds
  456. //
  457. // Entry: Pointer to destination time
  458. //
  459. // Exit: Nothing
  460. // ------------------------------
  461. #undef DPF_MODNAME
  462. #define DPF_MODNAME "DNTimeGet"
  463. void DNTimeGet( DN_TIME *const pTimeDestination )
  464. {
  465. static DN_TIME Time = { 0 };
  466. DN_TIME DeltaT;
  467. DWORD dwCurrentTime;
  468. DNASSERT( pTimeDestination != NULL );
  469. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  470. DNEnterCriticalSection( &g_TimeLock );
  471. //
  472. // we'll assume that we're getting called more than once every 40 days
  473. // so time wraps can be easily accounted for
  474. //
  475. dwCurrentTime = GETTIMESTAMP();
  476. DeltaT.Time32.TimeHigh = 0;
  477. DeltaT.Time32.TimeLow = dwCurrentTime - g_dwLastTimeCall;
  478. if ( DeltaT.Time32.TimeLow > 0x7FFFFFFF )
  479. {
  480. DNASSERT( FALSE );
  481. DeltaT.Time32.TimeLow = -static_cast<INT>( DeltaT.Time32.TimeLow );
  482. }
  483. g_dwLastTimeCall = dwCurrentTime;
  484. DNTimeAdd( &Time, &DeltaT, &Time );
  485. DBG_CASSERT( sizeof( *pTimeDestination ) == sizeof( Time ) );
  486. memcpy( pTimeDestination, &Time, sizeof( *pTimeDestination ) );
  487. DNLeaveCriticalSection( &g_TimeLock );
  488. }
  489. //**********************************************************************
  490. //**********************************************************************
  491. // ------------------------------
  492. // DNTimeCompare - compare two times
  493. //
  494. // Entry: Pointer to time1
  495. // Pointer to time2
  496. //
  497. // Exit: Value indicating relative magnitude
  498. // -1 = *pTime1 < *pTime2
  499. // 0 = *pTime1 == *pTime2
  500. // 1 = *pTime1 > *pTime2
  501. //
  502. // Notes: This function comes in 32-bit and 64-bit flavors. This function
  503. // will result in a compile error if compiled on an unsupported platform.
  504. // ------------------------------
  505. #undef DPF_MODNAME
  506. #define DPF_MODNAME "DNTimeCompare"
  507. INT_PTR DNTimeCompare( const DN_TIME *const pTime1, const DN_TIME *const pTime2 )
  508. {
  509. UINT_PTR iReturnValue;
  510. DNASSERT( pTime1 != NULL );
  511. DNASSERT( pTime2 != NULL );
  512. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  513. #pragma TODO( johnkan, "Should this be inlined?" )
  514. //#ifdef _WIN32
  515. if ( pTime1->Time32.TimeHigh < pTime2->Time32.TimeHigh )
  516. {
  517. iReturnValue = -1;
  518. }
  519. else
  520. {
  521. if ( pTime1->Time32.TimeHigh > pTime2->Time32.TimeHigh )
  522. {
  523. iReturnValue = 1;
  524. }
  525. else
  526. {
  527. if ( pTime1->Time32.TimeLow < pTime2->Time32.TimeLow )
  528. {
  529. iReturnValue = -1;
  530. }
  531. else
  532. {
  533. if ( pTime1->Time32.TimeLow == pTime2->Time32.TimeLow )
  534. {
  535. iReturnValue = 0;
  536. }
  537. else
  538. {
  539. iReturnValue = 1;
  540. }
  541. }
  542. }
  543. }
  544. //#endif // _WIN32
  545. //#ifdef _WIN64
  546. // // debug me!
  547. // DNASSERT( FALSE );
  548. //
  549. // if ( pTime1->Time < pTime2->Time )
  550. // {
  551. // iReturnValue = -1;
  552. // }
  553. // else
  554. // {
  555. // if ( pTime1->Time == pTime2->Time )
  556. // {
  557. // iReturnValue = 0;
  558. // }
  559. // else
  560. // {
  561. // iReturnValue = 1;
  562. // }
  563. // }
  564. //#endif // _WIN64
  565. return iReturnValue;
  566. }
  567. //**********************************************************************
  568. //**********************************************************************
  569. // ------------------------------
  570. // DNTimeAdd - add two times
  571. //
  572. // Entry: Pointer to time1
  573. // Pointer to time2
  574. // Pointer to time result
  575. //
  576. // Exit: Nothing
  577. //
  578. // Note: This function assumes that the time calculation won't wrap!
  579. // ------------------------------
  580. #undef DPF_MODNAME
  581. #define DPF_MODNAME "DNTimeAdd"
  582. void DNTimeAdd( const DN_TIME *const pTime1, const DN_TIME *const pTime2, DN_TIME *const pTimeResult )
  583. {
  584. DNASSERT( pTime1 != NULL );
  585. DNASSERT( pTime2 != NULL );
  586. DNASSERT( pTimeResult != NULL );
  587. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  588. #pragma TODO( johnkan, "Should this be inlined?" )
  589. #ifdef _X86_
  590. _asm { mov ecx, pTime1
  591. mov eax, ( DN_TIME [ ecx ] ).Time32.TimeLow;
  592. mov edx, ( DN_TIME [ ecx ] ).Time32.TimeHigh
  593. mov ecx, pTime2
  594. add eax, ( DN_TIME [ ecx ] ).Time32.TimeLow
  595. adc edx, ( DN_TIME [ ecx ] ).Time32.TimeHigh
  596. mov ecx, pTimeResult
  597. mov ( DN_TIME [ ecx ] ).Time32.TimeLow, eax
  598. mov ( DN_TIME [ ecx ] ).Time32.TimeHigh, edx
  599. };
  600. #else // _X86_
  601. /*
  602. #ifdef _ALPHA_
  603. // debug me
  604. DebugBreak();
  605. __asm{ mov $t0, *pTime1
  606. mov $t1, *pTime2
  607. addq $t0, $t1
  608. mov *pTimeResult, $t0
  609. };
  610. #else // _ALPHA_
  611. */
  612. //#ifdef _WIN32
  613. DWORD dwTempLowTime;
  614. dwTempLowTime = pTime1->Time32.TimeLow;
  615. pTimeResult->Time32.TimeLow = pTime1->Time32.TimeLow + pTime2->Time32.TimeLow;
  616. pTimeResult->Time32.TimeHigh = pTime1->Time32.TimeHigh + pTime2->Time32.TimeHigh;
  617. //
  618. // check for overflow in low 32-bits and increment high value if applicable
  619. //
  620. if ( pTimeResult->Time32.TimeLow < dwTempLowTime )
  621. {
  622. pTimeResult->Time32.TimeHigh++;
  623. }
  624. //#endif // _WIN32
  625. //#ifdef _WIN64
  626. // DEBUG_ONLY( UINT_PTR ReferenceTime );
  627. //
  628. // // debug me!
  629. // DNASSERT( FALSE );
  630. //
  631. // DEBUG_ONLY( ReferenceTime = pTime1->Time );
  632. // *pTimeResult = pTime1->Time + pTime2->Time;
  633. // DNASSERT( *pTimeResult >= ReferenceTime );
  634. //
  635. //#endif // _WIN64
  636. // #endif // _ALPHA_
  637. #endif // _X86_
  638. }
  639. //**********************************************************************
  640. //**********************************************************************
  641. // ------------------------------
  642. // DNTimeSubtract - subtract two times
  643. //
  644. // Entry: Pointer to time1
  645. // Pointer to time2
  646. // Pointer to time result
  647. //
  648. // Exit: Nothing
  649. //
  650. // Notes: This function assumes no underflow!
  651. // ------------------------------
  652. #undef DPF_MODNAME
  653. #define DPF_MODNAME "DNTimeSubtract"
  654. void DNTimeSubtract( const DN_TIME *const pTime1, const DN_TIME *const pTime2, DN_TIME *const pTimeResult )
  655. {
  656. DNASSERT( pTime1 != NULL );
  657. DNASSERT( pTime2 != NULL );
  658. DNASSERT( pTimeResult != NULL );
  659. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  660. #pragma TODO( johnkan, "Should this be inlined?" )
  661. #ifdef _X86_
  662. _asm { mov ecx, pTime1
  663. mov eax, ( DN_TIME [ ecx ] ).Time32.TimeLow
  664. mov edx, ( DN_TIME [ ecx ] ).Time32.TimeHigh
  665. mov ecx, pTime2
  666. sub eax, ( DN_TIME [ ecx ] ).Time32.TimeLow
  667. sbb edx, ( DN_TIME [ ecx ] ).Time32.TimeHigh
  668. mov ecx, pTimeResult
  669. mov ( DN_TIME [ ecx ] ).Time32.TimeLow, eax
  670. mov ( DN_TIME [ ecx ] ).Time32.TimeHigh, edx
  671. };
  672. #else // _X86_
  673. /*
  674. #ifdef _ALPHA_
  675. // debug me
  676. DebugBreak();
  677. mov $t0, *pTime1
  678. mov $t1, *pTime2
  679. addq $t0, $t1
  680. mov *pTimeResult, $t0
  681. #else // _ALPHA_
  682. */
  683. //#ifdef _WIN32
  684. DWORD dwTempLowTime;
  685. dwTempLowTime = pTime1->Time32.TimeLow;
  686. pTimeResult->Time32.TimeLow = pTime1->Time32.TimeLow - pTime2->Time32.TimeLow;
  687. pTimeResult->Time32.TimeHigh = pTime1->Time32.TimeHigh - pTime2->Time32.TimeHigh;
  688. //
  689. // check for underflow in low 32-bits and decrement high value if applicable
  690. //
  691. if ( pTimeResult->Time32.TimeLow > dwTempLowTime )
  692. {
  693. pTimeResult->Time32.TimeHigh--;
  694. }
  695. //#endif // _WIN32
  696. //#ifdef _WIN64
  697. // // debug me!
  698. // DNASSERT( FALSE );
  699. //
  700. // DNASSERT( pTime1->Time > pTime2->Time );
  701. // pTimeResult = pTime1->Time - pTime2->Time;
  702. //#endif // _WIN64
  703. // #endif // _ALPHA_
  704. #endif // _X86_
  705. }
  706. //**********************************************************************
  707. //**********************************************************************
  708. // ------------------------------
  709. // DNInitializeCriticalSection - initialize a critical section
  710. //
  711. // Entry: Pointer to critical section
  712. //
  713. // Exit: Boolean indicating success
  714. // TRUE = success
  715. // FALSE = failue
  716. // ------------------------------
  717. #undef DPF_MODNAME
  718. #define DPF_MODNAME "DNInitializeCriticalSection"
  719. BOOL DNInitializeCriticalSection( DNCRITICAL_SECTION *const pCriticalSection )
  720. {
  721. BOOL fReturn;
  722. DNASSERT( pCriticalSection != NULL );
  723. fReturn = TRUE;
  724. memset( pCriticalSection, 0x00, sizeof( *pCriticalSection ) );
  725. #ifdef DN_CRITICAL_SECTION_TRACKING
  726. pCriticalSection->OwningThreadID = DN_INVALID_THREAD_ID;
  727. pCriticalSection->MaxLockCount = -1;
  728. #endif // DN_CRITICAL_SECTION_TRACKING
  729. //
  730. // attempt to enter the critical section once
  731. //
  732. _try
  733. {
  734. // Do this for Win95 support only
  735. if (g_pfnInitializeCriticalSectionAndSpinCount)
  736. {
  737. // Pre-allocate the critsec event by setting the high bit of the spin count and set spin to 1000
  738. // Win98 and up map calls to this function to InitializeCriticalSection which makes sense since
  739. // 9x only uses one processor. NT also converts the spin to 0 for single proc machines.
  740. fReturn = g_pfnInitializeCriticalSectionAndSpinCount( &pCriticalSection->CriticalSection , 0x80000000 | 1000);
  741. // Believe it or not Win9x defines this function as returning VOID so its return value is garbage
  742. if (g_OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
  743. {
  744. fReturn = TRUE;
  745. }
  746. }
  747. else
  748. {
  749. InitializeCriticalSection( &pCriticalSection->CriticalSection );
  750. }
  751. }
  752. _except( EXCEPTION_EXECUTE_HANDLER )
  753. {
  754. fReturn = FALSE;
  755. }
  756. _try
  757. {
  758. if (fReturn)
  759. {
  760. EnterCriticalSection( &pCriticalSection->CriticalSection );
  761. }
  762. }
  763. _except( EXCEPTION_EXECUTE_HANDLER )
  764. {
  765. DeleteCriticalSection(&pCriticalSection->CriticalSection);
  766. fReturn = FALSE;
  767. }
  768. //
  769. // if we didn't fail on entering the critical section, make sure
  770. // we release it
  771. //
  772. if ( fReturn != FALSE )
  773. {
  774. LeaveCriticalSection( &pCriticalSection->CriticalSection );
  775. #ifdef DN_CRITICAL_SECTION_TRACKING
  776. pCriticalSection->AllocCallStack.NoteCurrentCallStack();
  777. // NOTE: We will not add g_CSLock to our list
  778. if (pCriticalSection != &g_CSLock)
  779. {
  780. DNEnterCriticalSection(&g_CSLock);
  781. pCriticalSection->blCritSec.InsertBefore(&g_blCritSecs);
  782. DNLeaveCriticalSection(&g_CSLock);
  783. }
  784. #endif
  785. }
  786. return fReturn;
  787. }
  788. //**********************************************************************
  789. //**********************************************************************
  790. // ------------------------------
  791. // DNDeleteCriticalSection - delete a critical section
  792. //
  793. // Entry: Pointer to critical section
  794. //
  795. // Exit: Nothing
  796. //
  797. // Notes: This function wrapping is overkill, but we're closing down so
  798. // the overhead is negligible.
  799. // ------------------------------
  800. #undef DPF_MODNAME
  801. #define DPF_MODNAME "DNDeleteCriticalSection"
  802. void DNDeleteCriticalSection( DNCRITICAL_SECTION *const pCriticalSection )
  803. {
  804. DNASSERT( pCriticalSection != NULL );
  805. DNASSERT( g_fOSIndirectionLayerInitialized != FALSE );
  806. #ifdef DN_CRITICAL_SECTION_TRACKING
  807. DNASSERT( pCriticalSection->LockCount == 0 );
  808. // NOTE: We will not remove g_CSLock from our list since we never added it
  809. if (pCriticalSection != &g_CSLock)
  810. {
  811. DNEnterCriticalSection(&g_CSLock);
  812. pCriticalSection->blCritSec.RemoveFromList();
  813. DNLeaveCriticalSection(&g_CSLock);
  814. }
  815. #endif
  816. DeleteCriticalSection( &pCriticalSection->CriticalSection );
  817. memset( &pCriticalSection->CriticalSection, 0x00, sizeof( pCriticalSection->CriticalSection ) );
  818. }
  819. //**********************************************************************
  820. #ifdef DN_MEMORY_TRACKING
  821. //**********************************************************************
  822. //**
  823. //** THIS IS THE MEMORY TRACKING SECTION. ONLY ADD FUNCTIONS HERE THAT ARE
  824. //** FOR MEMORY TRACKING!!
  825. //**
  826. //**********************************************************************
  827. //
  828. // Structure prepended to memory allocations to check for leaks.
  829. // Disable warning 4200 (zero sized structure elements).
  830. //
  831. #pragma warning ( disable : 4200 )
  832. typedef struct _MEMORY_LINK
  833. {
  834. public:
  835. void Initialize( void )
  836. {
  837. m_pNext = this;
  838. m_pPrev = this;
  839. }
  840. BOOL IsValid( void ) const
  841. {
  842. return ( m_Checksum == ( reinterpret_cast<UINT_PTR>( m_pPrev ) ^
  843. reinterpret_cast<UINT_PTR>( m_pNext ) ^
  844. m_Size ^
  845. MEMORY_CRC ) );
  846. }
  847. void UpdateCRC( void )
  848. {
  849. m_Checksum = reinterpret_cast<UINT_PTR>( m_pPrev ) ^
  850. reinterpret_cast<UINT_PTR>( m_pNext ) ^
  851. m_Size ^
  852. MEMORY_CRC;
  853. }
  854. BOOL IsEmpty( void ) { return ( ( m_pNext == this ) && ( m_pPrev == this ) ); }
  855. _MEMORY_LINK *GetNext( void ) const { return m_pNext; }
  856. _MEMORY_LINK *GetPrev( void ) const { return m_pPrev; }
  857. void *GetDataPointer( void ) { return &m_Data[ sizeof( DWORD_PTR ) ]; }
  858. static _MEMORY_LINK *PointerFromData( void *const pData )
  859. {
  860. return reinterpret_cast<_MEMORY_LINK*>( &( reinterpret_cast<BYTE*>( pData )[ - ( OFFSETOF( MEMORY_LINK, m_Data ) + static_cast<int>( sizeof( DWORD_PTR ) ) ) ] ) );
  861. }
  862. void SetSize( const UINT_PTR Size ){ m_Size = Size; }
  863. UINT_PTR GetSize( void ) const { return m_Size; }
  864. #undef DPF_MODNAME
  865. #define DPF_MODNAME "_MEMORY_LINK::LinkAfterOther"
  866. void LinkAfterOther( _MEMORY_LINK &OtherLink )
  867. {
  868. ASSERT( OtherLink.IsValid() != FALSE );
  869. if ( OtherLink.m_pNext != NULL )
  870. {
  871. ASSERT( OtherLink.m_pNext->IsValid() != FALSE );
  872. OtherLink.m_pNext->m_pPrev = this;
  873. OtherLink.m_pNext->UpdateCRC();
  874. }
  875. m_pNext = OtherLink.m_pNext;
  876. m_pPrev = &OtherLink;
  877. UpdateCRC();
  878. OtherLink.m_pNext = this;
  879. OtherLink.UpdateCRC();
  880. }
  881. #undef DPF_MODNAME
  882. #define DPF_MODNAME "_MEMORY_LINK::RemoveFromList"
  883. void RemoveFromList( void )
  884. {
  885. ASSERT( IsValid() != FALSE );
  886. ASSERT( m_pPrev != NULL );
  887. if ( m_pNext != NULL )
  888. {
  889. ASSERT( m_pNext->IsValid() != FALSE );
  890. m_pNext->m_pPrev = m_pPrev;
  891. m_pNext->UpdateCRC();
  892. }
  893. ASSERT( m_pPrev->IsValid() != FALSE );
  894. m_pPrev->m_pNext = m_pNext;
  895. m_pPrev->UpdateCRC();
  896. m_pNext = NULL;
  897. m_pPrev = NULL;
  898. }
  899. void NoteCurrentCallStack( void ) { m_CallStack.NoteCurrentCallStack(); }
  900. void GetCallStack( char *const pBuffer ) const { m_CallStack.GetCallStackString( pBuffer ); }
  901. void SetOverrunSignatures( void )
  902. {
  903. *reinterpret_cast<DWORD_PTR*>( m_Data ) = GUARD_SIGNATURE;
  904. // 6/30/2000(RichGr) - IA64: Specifying UNALIGNED generates the correct IA64 code for non-8-byte alignment.
  905. *reinterpret_cast<UNALIGNED DWORD_PTR*>( &m_Data[ m_Size + sizeof( DWORD_PTR ) ] ) = GUARD_SIGNATURE;
  906. }
  907. BOOL UnderrunDetected( void ) const { return ( *reinterpret_cast<const DWORD_PTR*>( m_Data ) != GUARD_SIGNATURE ); }
  908. // 6/30/2000(RichGr) - IA64: Specifying UNALIGNED generates the correct IA64 code for non-8-byte alignment.
  909. BOOL OverrunDetected( void ) const { return ( *reinterpret_cast<const UNALIGNED DWORD_PTR*>( &m_Data[ m_Size + sizeof( DWORD_PTR ) ] ) != GUARD_SIGNATURE ); }
  910. BOOL IsCorrupted( void ) const { return ( !IsValid() || UnderrunDetected() || OverrunDetected() ); }
  911. protected:
  912. private:
  913. UINT_PTR m_Checksum;
  914. UINT_PTR m_Size;
  915. _MEMORY_LINK *m_pPrev;
  916. _MEMORY_LINK *m_pNext;
  917. CCallStack<DN_MEMORY_CALL_STACK_DEPTH> m_CallStack;
  918. BYTE m_Data[];
  919. } MEMORY_LINK;
  920. #pragma warning ( default : 4200 )
  921. //
  922. // forward structure references
  923. //
  924. typedef struct _MEMORY_LINK MEMORY_LINK;
  925. //
  926. // memory tracking variables
  927. //
  928. static UINT_PTR g_uAllocatedMemoryCount;
  929. static MEMORY_LINK g_AllocatedMemory;
  930. //**********************************************************************
  931. // ------------------------------
  932. // DNMemoryTrackInitialize - initialize memory tracking
  933. //
  934. // Entry: Nothing
  935. //
  936. // Exit: Error code
  937. // ------------------------------
  938. #undef DPF_MODNAME
  939. #define DPF_MODNAME "DNMemoryTrackInitialize"
  940. static BOOL DNMemoryTrackInitialize( void )
  941. {
  942. BOOL fReturn;
  943. fReturn = TRUE;
  944. memset( &g_AllocatedMemory, 0x00, sizeof ( g_AllocatedMemory ) );
  945. g_uAllocatedMemoryCount = 0;
  946. g_AllocatedMemory.Initialize();
  947. g_AllocatedMemory.UpdateCRC();
  948. InitializeCriticalSection( &g_AllocatedMemoryLock );
  949. return fReturn;
  950. }
  951. //**********************************************************************
  952. //**********************************************************************
  953. //**********************************************************************
  954. // ------------------------------
  955. // DNMemoryTrackHeapAlloc - allocate from heap and track allocations
  956. //
  957. // Entry: Size of memory to allocate
  958. //
  959. // Exit: Pointer to allocated memory
  960. // ------------------------------
  961. #undef DPF_MODNAME
  962. #define DPF_MODNAME "DNMemoryTrackHeapAlloc"
  963. void *DNMemoryTrackHeapAlloc( const UINT_PTR Size )
  964. {
  965. UINT_PTR RequiredSize;
  966. MEMORY_LINK *pMemoryLink;
  967. void *pReturn;
  968. //
  969. // Voice and lobby currently try allocating 0 byte buffers, can't enable this check yet.
  970. //
  971. //ASSERT( Size > 0 );
  972. RequiredSize = Size + sizeof( MEMORY_LINK ) + ( sizeof( DWORD_PTR ) * 2 );
  973. DNMemoryTrackingValidateMemory();
  974. pMemoryLink = static_cast<MEMORY_LINK*>( HeapAlloc( g_hMemoryHeap, 0, RequiredSize ) );
  975. if ( pMemoryLink != NULL )
  976. {
  977. pMemoryLink->Initialize();
  978. EnterCriticalSection( &g_AllocatedMemoryLock );
  979. g_uAllocatedMemoryCount++;
  980. pMemoryLink->SetSize( Size );
  981. pMemoryLink->LinkAfterOther( g_AllocatedMemory );
  982. pMemoryLink->NoteCurrentCallStack();
  983. pMemoryLink->SetOverrunSignatures();
  984. LeaveCriticalSection( &g_AllocatedMemoryLock );
  985. pReturn = pMemoryLink->GetDataPointer();
  986. }
  987. else
  988. {
  989. pReturn = NULL;
  990. }
  991. return pReturn;
  992. }
  993. //**********************************************************************
  994. //**********************************************************************
  995. // ------------------------------
  996. // DNMemoryTrackHeapReAlloc - reallocate from heap and track allocations
  997. //
  998. // Entry: Pointer to old memory
  999. // Size of memory to allocate
  1000. //
  1001. // Exit: Pointer to allocated memory
  1002. // ------------------------------
  1003. #undef DPF_MODNAME
  1004. #define DPF_MODNAME "DNMemoryTrackHeapReAlloc"
  1005. void *DNMemoryTrackHeapReAlloc( void *const pMemory, const UINT_PTR MemorySize )
  1006. {
  1007. UINT_PTR RequiredSize;
  1008. MEMORY_LINK *pMemoryLink;
  1009. void *pReturn;
  1010. ASSERT( pMemory != NULL );
  1011. //
  1012. // Voice and lobby currently try allocating 0 byte buffers, can't enable this check yet.
  1013. //
  1014. //ASSERT( MemorySize > 0 );
  1015. pMemoryLink = MEMORY_LINK::PointerFromData( pMemory );
  1016. DNMemoryTrackingValidateMemory();
  1017. EnterCriticalSection( &g_AllocatedMemoryLock );
  1018. g_uAllocatedMemoryCount--;
  1019. pMemoryLink->RemoveFromList();
  1020. pMemoryLink->SetSize( 0 );
  1021. LeaveCriticalSection( &g_AllocatedMemoryLock );
  1022. RequiredSize = MemorySize + sizeof( MEMORY_LINK ) + ( sizeof( DWORD_PTR ) * 2 );
  1023. pMemoryLink = static_cast<MEMORY_LINK*>( HeapReAlloc( g_hMemoryHeap, 0, pMemoryLink, RequiredSize ) );
  1024. if ( pMemoryLink != NULL )
  1025. {
  1026. EnterCriticalSection( &g_AllocatedMemoryLock );
  1027. g_uAllocatedMemoryCount++;
  1028. pMemoryLink->SetSize( MemorySize );
  1029. pMemoryLink->LinkAfterOther( g_AllocatedMemory );
  1030. pMemoryLink->SetOverrunSignatures();
  1031. LeaveCriticalSection( & g_AllocatedMemoryLock );
  1032. pReturn = pMemoryLink->GetDataPointer();
  1033. }
  1034. else
  1035. {
  1036. pReturn = NULL;
  1037. }
  1038. return pReturn;
  1039. }
  1040. //**********************************************************************
  1041. //**********************************************************************
  1042. // ------------------------------
  1043. // DNMemoryTrackHeapFree - free from heap and track memory
  1044. //
  1045. // Entry: Pointer to old memory
  1046. //
  1047. // Exit: Nothing
  1048. // ------------------------------
  1049. #undef DPF_MODNAME
  1050. #define DPF_MODNAME "DNMemoryTrackHeapFree"
  1051. void DNMemoryTrackHeapFree( void *const pMemory )
  1052. {
  1053. MEMORY_LINK *pMemoryLink;
  1054. ASSERT( pMemory != NULL );
  1055. DNMemoryTrackingValidateMemory();
  1056. pMemoryLink = MEMORY_LINK::PointerFromData( pMemory );
  1057. EnterCriticalSection( &g_AllocatedMemoryLock );
  1058. g_uAllocatedMemoryCount--;
  1059. pMemoryLink->RemoveFromList();
  1060. pMemoryLink->SetSize( 0 );
  1061. LeaveCriticalSection( &g_AllocatedMemoryLock );
  1062. HeapFree( g_hMemoryHeap, 0, pMemoryLink );
  1063. }
  1064. //**********************************************************************
  1065. //**********************************************************************
  1066. // ------------------------------
  1067. // DNMemoryTrackValidateMemory - validate allocated memory
  1068. //
  1069. // Entry: Nothing
  1070. //
  1071. // Exit: Nothing
  1072. // ------------------------------
  1073. #undef DPF_MODNAME
  1074. #define DPF_MODNAME "DNMemoryTrackingValidateMemory"
  1075. void DNMemoryTrackingValidateMemory( void )
  1076. {
  1077. MEMORY_LINK *pMemoryLink;
  1078. char CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
  1079. //
  1080. // validate all of the allocated memory
  1081. //
  1082. EnterCriticalSection( &g_AllocatedMemoryLock );
  1083. pMemoryLink = g_AllocatedMemory.GetNext();
  1084. while ( pMemoryLink != &g_AllocatedMemory )
  1085. {
  1086. if ( pMemoryLink->IsCorrupted() != FALSE )
  1087. {
  1088. UINT_PTR MessageReturn;
  1089. char MessageString[ 1000 ];
  1090. wsprintf( MessageString,
  1091. // 7/28/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers and handles.
  1092. #ifdef _IA64_
  1093. // 8/05/2000(RichGr) - IA64: GetSize() returns UINT_PTR (64-bit), so we may as well handle in hex as %d expects a DWORD.
  1094. "Memory block: 0x%p\tAllocated size: 0x%p bytes\nCorruption Type: ",
  1095. #else
  1096. "Memory block: 0x%08x\tAllocated size: %d bytes\nCorruption Type: ",
  1097. #endif
  1098. pMemoryLink->GetDataPointer(),
  1099. pMemoryLink->GetSize() );
  1100. if ( !pMemoryLink->IsValid() )
  1101. {
  1102. strcat( MessageString, " ,INVALID LINK");
  1103. }
  1104. if ( pMemoryLink->UnderrunDetected() )
  1105. {
  1106. strcat( MessageString, " ,UNDERRUN DETECTED");
  1107. }
  1108. if ( pMemoryLink->OverrunDetected() )
  1109. {
  1110. strcat( MessageString, " ,OVERRUN DETECTED");
  1111. }
  1112. pMemoryLink->GetCallStack( CallStackBuffer );
  1113. MessageReturn = DisplayCallStack( MessageString, "Memory Corruption!", CallStackBuffer );
  1114. switch ( MessageReturn )
  1115. {
  1116. case IDABORT:
  1117. {
  1118. DNASSERT( FALSE );
  1119. break;
  1120. }
  1121. case IDIGNORE:
  1122. {
  1123. //
  1124. // You're probably going to get stopped in the heap
  1125. // manager!!!
  1126. //
  1127. break;
  1128. }
  1129. case IDRETRY:
  1130. {
  1131. DNASSERT( FALSE );
  1132. break;
  1133. }
  1134. }
  1135. }
  1136. pMemoryLink = pMemoryLink->GetNext();
  1137. }
  1138. LeaveCriticalSection( &g_AllocatedMemoryLock );
  1139. //
  1140. // ask the OS to validate the heap
  1141. //
  1142. if ( HeapValidate( g_hMemoryHeap, 0, NULL ) == FALSE )
  1143. {
  1144. DNASSERT( FALSE );
  1145. }
  1146. }
  1147. //**********************************************************************
  1148. //**********************************************************************
  1149. // ------------------------------
  1150. // DNMemoryTrackDisplayMemoryLeaks - display memory leaks
  1151. //
  1152. // Entry: Nothing
  1153. //
  1154. // Exit: Nothing
  1155. // ------------------------------
  1156. #undef DPF_MODNAME
  1157. #define DPF_MODNAME "DNMemoryTrackDisplayMemoryLeaks"
  1158. static void DNMemoryTrackDisplayMemoryLeaks( void )
  1159. {
  1160. BOOL fDisplayLeaks;
  1161. UINT_PTR uMaxMemoryLeakCount;
  1162. UINT_PTR uMemoryLeakIndex;
  1163. //
  1164. // initialize
  1165. //
  1166. fDisplayLeaks = TRUE;
  1167. uMaxMemoryLeakCount = g_uAllocatedMemoryCount;
  1168. uMemoryLeakIndex = 0;
  1169. //
  1170. // Check for outstanding memory allocations.
  1171. //
  1172. while ( g_AllocatedMemory.IsEmpty() == FALSE )
  1173. {
  1174. MEMORY_LINK *pTemp;
  1175. UINT_PTR MessageReturn;
  1176. char CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
  1177. char LeakSizeString[ 50 ];
  1178. char DialogTitle[ 1000 ];
  1179. pTemp = g_AllocatedMemory.GetNext();
  1180. uMemoryLeakIndex++;
  1181. // 7/28/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers and handles.
  1182. #ifdef _IA64_
  1183. // 8/05/2000(RichGr) - IA64: GetSize() returns UINT_PTR (64-bit), so we may as well handle in hex as %d expects a DWORD.
  1184. wsprintf( LeakSizeString, "0x%p bytes leaked at address 0x%p!\n", pTemp->GetSize(), pTemp->GetDataPointer() );
  1185. #else
  1186. wsprintf( LeakSizeString, "%d bytes leaked at address 0x%08x!\n", pTemp->GetSize(), pTemp->GetDataPointer() );
  1187. #endif
  1188. wsprintf( DialogTitle,
  1189. "DirectPlay8 memory leak detected! ( #%d of %d )",
  1190. uMemoryLeakIndex,
  1191. uMaxMemoryLeakCount );
  1192. pTemp->GetCallStack( CallStackBuffer );
  1193. if ( ( g_dwMemLeakDisplayFlags & MEMORY_LEAK_REPORT_DPF ) != 0 )
  1194. {
  1195. DPFX(DPFPREP, 0, "%s%s%s\n", DialogTitle, LeakSizeString, CallStackBuffer );
  1196. }
  1197. if ( ( g_dwMemLeakDisplayFlags & MEMORY_LEAK_REPORT_DIALOG ) != 0 )
  1198. {
  1199. if ( fDisplayLeaks != FALSE )
  1200. {
  1201. MessageReturn = DisplayCallStack( LeakSizeString, DialogTitle, CallStackBuffer );
  1202. switch ( MessageReturn )
  1203. {
  1204. //
  1205. // stop application now
  1206. //
  1207. case IDABORT:
  1208. {
  1209. fDisplayLeaks = FALSE;
  1210. break;
  1211. }
  1212. //
  1213. // display next leak
  1214. //
  1215. case IDIGNORE:
  1216. {
  1217. break;
  1218. }
  1219. //
  1220. // stop in the debugger
  1221. //
  1222. case IDRETRY:
  1223. {
  1224. DNASSERT( FALSE );
  1225. break;
  1226. }
  1227. //
  1228. // unknown
  1229. //
  1230. default:
  1231. {
  1232. DNASSERT( FALSE );
  1233. break;
  1234. }
  1235. }
  1236. }
  1237. }
  1238. DNFree( pTemp->GetDataPointer() );
  1239. }
  1240. }
  1241. //**********************************************************************
  1242. //**********************************************************************
  1243. //**
  1244. //** THIS IS THE END OF THE MEMORY LOGGING SECTION.
  1245. //**
  1246. //**********************************************************************
  1247. #endif // DN_MEMORY_TRACKING
  1248. #if defined( DN_MEMORY_TRACKING ) || defined( DN_CRITICAL_SECTION_TRACKING )
  1249. //**********************************************************************
  1250. // ------------------------------
  1251. // DisplayCallStack - display a call stack message box
  1252. //
  1253. // Entry: Pointer to information string
  1254. // Pointer to title string
  1255. // Pointer to call stack string
  1256. //
  1257. // Exit: Dialog return code
  1258. // ------------------------------
  1259. #undef DPF_MODNAME
  1260. #define DPF_MODNAME "DisplayCallStack"
  1261. static int DisplayCallStack( const char *const pszMsg, const char *const pszTitle, const char *const pCallStackString )
  1262. {
  1263. MSGBOXPARAMS MessageBoxParams;
  1264. char szStackTraceMsg[ CALLSTACK_BUFFER_SIZE ];
  1265. _snprintf(szStackTraceMsg, CALLSTACK_BUFFER_SIZE-1, "%s%s", pszMsg, pCallStackString);
  1266. //
  1267. // display message box
  1268. //
  1269. memset( &MessageBoxParams, 0x00, sizeof( MessageBoxParams ) );
  1270. MessageBoxParams.cbSize = sizeof( MessageBoxParams );
  1271. MessageBoxParams.lpszText = szStackTraceMsg;
  1272. MessageBoxParams.lpszCaption = pszTitle;
  1273. MessageBoxParams.dwStyle = MB_ABORTRETRYIGNORE | MB_SETFOREGROUND | MB_TOPMOST | MB_DEFBUTTON2;
  1274. MessageBoxParams.hInstance = NULL;
  1275. return MessageBoxIndirect( &MessageBoxParams );
  1276. }
  1277. //**********************************************************************
  1278. //**********************************************************************
  1279. //**
  1280. //** END OF CALL STACK TRACKING SECTION.
  1281. //**
  1282. //**********************************************************************
  1283. #endif // defined( DN_MEMORY_TRACKING ) || defined( DN_CRITICAL_SECTION_TRACKING )
  1284. #ifdef DN_CRITICAL_SECTION_TRACKING
  1285. //**********************************************************************
  1286. //**
  1287. //** THIS IS THE CRITICAL-SECTION TRACKING SECTION. DON'T ADD FUNCTIONS HERE
  1288. //** THAT ARE NOT FOR CRITICAL SECTIONS!!
  1289. //**
  1290. //**********************************************************************
  1291. //**********************************************************************
  1292. // ------------------------------
  1293. // DNCSTrackInitialize - initialize critical section tracking code
  1294. //
  1295. // Entry: Nothing
  1296. //
  1297. // Exit: Boolean indicating success
  1298. // TRUE = initialization succeeded
  1299. // FALSE = initialization failed
  1300. // ------------------------------
  1301. #undef DPF_MODNAME
  1302. #define DPF_MODNAME "DNCSTrackInitialize"
  1303. static BOOL DNCSTrackInitialize( void )
  1304. {
  1305. g_blCritSecs.Initialize();
  1306. return DNInitializeCriticalSection(&g_CSLock);
  1307. }
  1308. //**********************************************************************
  1309. //**********************************************************************
  1310. // ------------------------------
  1311. // DNCSTrackSetCriticalSectionRecursionCount - set the maximum recursion depth
  1312. // allowed by a DNCRITICAL_SECTION.
  1313. //
  1314. // Entry: Pointer to critical section
  1315. // Recursion count
  1316. //
  1317. // Exit: Nothing
  1318. //
  1319. // Note: The recursion count is the number of times we allow reentry so
  1320. // we need to bais by one to allow the user to take the lock at
  1321. // least once.
  1322. // ------------------------------
  1323. #undef DPF_MODNAME
  1324. #define DPF_MODNAME "DNCSTrackSetCriticalRecursionCount"
  1325. void DNCSTrackSetCriticalSectionRecursionCount( DNCRITICAL_SECTION *const pCriticalSection, const UINT_PTR RecursionCount )
  1326. {
  1327. UINT_PTR LocalRecursionCount;
  1328. DNASSERT( pCriticalSection != NULL );
  1329. //
  1330. // make sure we don't overflow
  1331. //
  1332. LocalRecursionCount = RecursionCount;
  1333. if ( LocalRecursionCount == -1 )
  1334. {
  1335. LocalRecursionCount--;
  1336. }
  1337. pCriticalSection->MaxLockCount = LocalRecursionCount + 1;
  1338. DNASSERT( pCriticalSection->MaxLockCount != 0 );
  1339. }
  1340. //**********************************************************************
  1341. //**********************************************************************
  1342. // ------------------------------
  1343. // DNCSTrackEnterCriticalSection - enter a debug critical section
  1344. //
  1345. // Entry: Pointer to critical section
  1346. //
  1347. // Exit: Nothing
  1348. // ------------------------------
  1349. #undef DPF_MODNAME
  1350. #define DPF_MODNAME "DNCSTrackEnterCriticalSection"
  1351. void DNCSTrackEnterCriticalSection( DNCRITICAL_SECTION *const pCriticalSection )
  1352. {
  1353. UINT_PTR ThisThreadID;
  1354. static BOOL fDisplayCallStacks = TRUE;
  1355. DNASSERT( pCriticalSection != NULL );
  1356. EnterCriticalSection( &pCriticalSection->CriticalSection );
  1357. ThisThreadID = GetCurrentThreadId();
  1358. if ( pCriticalSection->OwningThreadID != ThisThreadID )
  1359. {
  1360. DNASSERT( pCriticalSection->OwningThreadID == DN_INVALID_THREAD_ID );
  1361. pCriticalSection->OwningThreadID = ThisThreadID;
  1362. DNASSERT( pCriticalSection->LockCount == 0 );
  1363. }
  1364. else
  1365. {
  1366. DNASSERT( pCriticalSection->LockCount != 0 );
  1367. }
  1368. if ( pCriticalSection->LockCount == 0 )
  1369. {
  1370. pCriticalSection->CallStack.NoteCurrentCallStack();
  1371. }
  1372. pCriticalSection->LockCount++;
  1373. if ( pCriticalSection->LockCount > pCriticalSection->MaxLockCount )
  1374. {
  1375. if ( pCriticalSection->MaxLockCount == 1 )
  1376. {
  1377. if ( fDisplayCallStacks != FALSE )
  1378. {
  1379. char CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
  1380. //
  1381. // Exceeded recursion depth of 1, display stack of call orignally
  1382. // holding the lock.
  1383. //
  1384. pCriticalSection->CallStack.GetCallStackString( CallStackBuffer );
  1385. switch ( DisplayCallStack( "Stack trace of function that originally held the lock:",
  1386. "DNCritical section has been reentered!",
  1387. CallStackBuffer ) )
  1388. {
  1389. //
  1390. // don't display any more critical section warnings!
  1391. //
  1392. case IDABORT:
  1393. {
  1394. fDisplayCallStacks = FALSE;
  1395. break;
  1396. }
  1397. //
  1398. // acknowledged
  1399. //
  1400. case IDIGNORE:
  1401. {
  1402. break;
  1403. }
  1404. //
  1405. // stop in debugger
  1406. //
  1407. case IDRETRY:
  1408. {
  1409. DNASSERT( FALSE );
  1410. break;
  1411. }
  1412. }
  1413. }
  1414. }
  1415. else
  1416. {
  1417. //
  1418. // exceeded recursion depth, check your code!!
  1419. //
  1420. DNASSERT( FALSE );
  1421. }
  1422. }
  1423. }
  1424. //**********************************************************************
  1425. //**********************************************************************
  1426. // ------------------------------
  1427. // DNCSTrackLeaveCriticalSection - leave a debug critical section
  1428. //
  1429. // Entry: Pointer to critical section
  1430. //
  1431. // Exit: Nothing
  1432. // ------------------------------
  1433. #undef DPF_MODNAME
  1434. #define DPF_MODNAME "DNCSTrackLeaveCriticalSection"
  1435. void DNCSTrackLeaveCriticalSection( DNCRITICAL_SECTION *const pCriticalSection )
  1436. {
  1437. DNASSERT( pCriticalSection != NULL );
  1438. DNASSERT( pCriticalSection->OwningThreadID == GetCurrentThreadId() );
  1439. DNASSERT( pCriticalSection->LockCount <= pCriticalSection->MaxLockCount );
  1440. DNASSERT( pCriticalSection->LockCount != 0 );
  1441. pCriticalSection->LockCount--;
  1442. if ( pCriticalSection->LockCount == 0 )
  1443. {
  1444. memset( &pCriticalSection->CallStack, 0x00, sizeof( pCriticalSection->CallStack ) );
  1445. pCriticalSection->OwningThreadID = DN_INVALID_THREAD_ID;
  1446. }
  1447. LeaveCriticalSection( &pCriticalSection->CriticalSection );
  1448. }
  1449. //**********************************************************************
  1450. //**********************************************************************
  1451. // ------------------------------
  1452. // DNCSTrackCriticalSectionIsTakenByThisThread - determine if this thread has taken a
  1453. // specific critical section
  1454. //
  1455. // Entry: Pointer to critical section
  1456. // Boolean condition to test for
  1457. //
  1458. // Exit: Nothing
  1459. // ------------------------------
  1460. #undef DPF_MODNAME
  1461. #define DPF_MODNAME "DNCSTrackCriticalSectionIsTakenByThisThread"
  1462. void DNCSTrackCriticalSectionIsTakenByThisThread( const DNCRITICAL_SECTION *const pCriticalSection, const BOOL fFlag )
  1463. {
  1464. ASSERT( fFlag == ( pCriticalSection->OwningThreadID == GetCurrentThreadId() ) )
  1465. }
  1466. //**********************************************************************
  1467. //**********************************************************************
  1468. //**
  1469. //** THIS IS THE END OF THE CRITICAL-SECTION TRACKING CODE.
  1470. //**
  1471. //**********************************************************************
  1472. #endif // DN_CRITICAL_SECTION_TRACKING