Leaked source code of windows server 2003
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.

568 lines
13 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: memalloc.c
  6. * Content: allocates memory
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 20-jan-95 craige initial implementation
  11. * 27-feb-95 craige don't call HeapFree with NULL, it is a huge time sink
  12. * 29-mar-95 craige memory tracker
  13. * 01-apr-95 craige happy fun joy updated header file
  14. * 06-apr-95 craige made stand-alone
  15. * 22-may-95 craige added MemAlloc16
  16. * 12-jun-95 craige added MemReAlloc
  17. * 18-jun-95 craige deadlock joy: don't take DLL csect here
  18. * 26-jul-95 toddla added MemSize and fixed MemReAlloc
  19. * 29-feb-96 colinmc added optional debugging code to blat a a specific
  20. * bit pattern over freed memory
  21. * 08-oct-96 ketand change debug message to give a total for the terminating
  22. * process
  23. *
  24. ***************************************************************************/
  25. #undef WIN32_LEAN_AND_MEAN
  26. #define WIN32_LEAN_AND_MEAN
  27. #include <windows.h>
  28. #include "memalloc.h"
  29. #include "dpf.h"
  30. #define FREE_MEMORY_PATTERN 0xDEADBEEFUL
  31. #define RESPATH_D3D "Software\\Microsoft\\Direct3D"
  32. #ifdef WIN95
  33. #ifdef NOSHARED
  34. #define HEAP_SHARED 0
  35. #else
  36. #define HEAP_SHARED 0x04000000 // put heap in shared memory
  37. #endif
  38. #else
  39. #define HEAP_SHARED 0
  40. #endif
  41. static HANDLE hHeap = NULL; // handle to shared heap for this DLL
  42. /*
  43. * memory track struct and list
  44. */
  45. #ifdef DEBUG
  46. #define MCOOKIE 0xbaaabaaa
  47. #define MCOOKIE_FREE 0xbabababa
  48. typedef struct _MEMTRACK
  49. {
  50. DWORD dwCookie;
  51. struct _MEMTRACK FAR *lpNext;
  52. struct _MEMTRACK FAR *lpPrev;
  53. DWORD dwSize;
  54. LPVOID lpAddr;
  55. DWORD dwPid;
  56. LONG lAllocID;
  57. } MEMTRACK, FAR *LPMEMTRACK;
  58. static LPMEMTRACK lpHead;
  59. static LPMEMTRACK lpTail;
  60. static LONG lAllocCount;
  61. static LONG lAllocID;
  62. static LONG lBreakOnAllocID;
  63. static LONG lBreakOnMemLeak;
  64. #if defined(_X86_)
  65. #define MyGetReturnAddress(first) (LPVOID) *(DWORD *)(((LPBYTE)&first)-4)
  66. #else
  67. #define MyGetReturnAddress(first) _ReturnAddress()
  68. #endif
  69. #define DEBUG_TRACK( lptr, first ) \
  70. if( lptr == NULL ) \
  71. { \
  72. DPF( 1, "Alloc of size %u FAILED!", size ); \
  73. } \
  74. else \
  75. { \
  76. LPMEMTRACK pmt; \
  77. pmt = (LPMEMTRACK) lptr; \
  78. pmt->dwSize = size - sizeof( MEMTRACK ); \
  79. pmt->dwCookie = MCOOKIE; \
  80. pmt->lpAddr = MyGetReturnAddress(first); \
  81. pmt->dwPid = GetCurrentProcessId(); \
  82. pmt->lAllocID = lAllocID; \
  83. if( lpHead == NULL ) \
  84. { \
  85. lpHead = lpTail = pmt; \
  86. } \
  87. else \
  88. { \
  89. lpTail->lpNext = pmt; \
  90. pmt->lpPrev = lpTail; \
  91. lpTail = pmt; \
  92. } \
  93. lptr = (LPVOID) (((LPBYTE) lptr) + sizeof( MEMTRACK )); \
  94. lAllocCount++; \
  95. if( lAllocID == lBreakOnAllocID ) \
  96. { \
  97. DebugBreak(); \
  98. } \
  99. lAllocID++; \
  100. }
  101. #define DEBUG_TRACK_UPDATE_SIZE( s ) s += sizeof( MEMTRACK );
  102. #else
  103. #define DEBUG_TRACK( lptr, first )
  104. #define DEBUG_TRACK_UPDATE_SIZE( size )
  105. #endif
  106. #ifndef __DXGUSEALLOC
  107. #if defined( WIN95 ) && defined( WANT_MEM16 )
  108. extern DWORD _stdcall MapLS( LPVOID ); // flat -> 16:16
  109. extern void _stdcall UnMapLS( DWORD ); // unmap 16:16
  110. typedef struct SELLIST {
  111. struct SELLIST *link;
  112. LPBYTE base;
  113. WORD sel;
  114. } SELLIST, *LPSELLIST;
  115. static LPSELLIST lpSelList;
  116. /*
  117. * MemAlloc16
  118. *
  119. * Allocate some memory, and return a 16:16 pointer to that memory
  120. *
  121. * NOTE: ASSUMES WE ARE IN THE DLL CRITICAL SECTION!
  122. */
  123. LPVOID __cdecl MemAlloc16( UINT size, LPDWORD p16 )
  124. {
  125. LPBYTE lptr;
  126. LPSELLIST psel;
  127. DWORD diff;
  128. DEBUG_TRACK_UPDATE_SIZE( size );
  129. lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size );
  130. DEBUG_TRACK( lptr, size );
  131. if( lptr == NULL )
  132. {
  133. return NULL;
  134. }
  135. /*
  136. * try to find an existing selector that maps this area
  137. */
  138. psel = lpSelList;
  139. while( psel != NULL )
  140. {
  141. if( psel->base <= lptr )
  142. {
  143. diff = lptr - psel->base;
  144. if( diff+size < 0xf000 )
  145. {
  146. *p16 = ((DWORD)psel->sel << 16l) + diff;
  147. return lptr;
  148. }
  149. }
  150. psel = psel->link;
  151. }
  152. /*
  153. * no selector found, create a new one
  154. */
  155. psel = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, sizeof( SELLIST ));
  156. if( psel == NULL )
  157. {
  158. return NULL;
  159. }
  160. psel->sel = HIWORD( MapLS( lptr ) );
  161. DPF( 2, "$$$$$$ New selector allocated: %04x", psel->sel );
  162. psel->base = lptr;
  163. psel->link = lpSelList;
  164. lpSelList = psel;
  165. *p16 = ((DWORD) psel->sel) << 16l;
  166. return lptr;
  167. } /* MemAlloc16 */
  168. /*
  169. * GetPtr16
  170. */
  171. LPVOID GetPtr16( LPVOID ptr )
  172. {
  173. DWORD diff;
  174. DWORD p16;
  175. LPSELLIST psel;
  176. LPBYTE lptr;
  177. lptr = ptr;
  178. psel = lpSelList;
  179. while( psel != NULL )
  180. {
  181. if( psel->base <= lptr )
  182. {
  183. diff = lptr - psel->base;
  184. if( diff <= 0xf000 )
  185. {
  186. p16 = ((DWORD)psel->sel << 16l) + diff;
  187. return (LPVOID) p16;
  188. }
  189. }
  190. psel = psel->link;
  191. }
  192. DPF( 1, "ERROR: NO 16:16 PTR for %08lx", lptr );
  193. return NULL;
  194. } /* GetPtr16 */
  195. /*
  196. * freeSelectors
  197. */
  198. static void freeSelectors( void )
  199. {
  200. LPSELLIST psel;
  201. LPSELLIST link;
  202. psel = lpSelList;
  203. while( psel != NULL )
  204. {
  205. link = psel->link;
  206. DPF( 2, "$$$$$$ Freeing selector %04x", psel->sel );
  207. UnMapLS( ((DWORD)psel->sel) << 16l );
  208. HeapFree( hHeap, 0, psel );
  209. psel = link;
  210. }
  211. lpSelList = NULL;
  212. } /* freeSelectors */
  213. #endif
  214. #endif //!__DXGUSEALLOC
  215. /*
  216. * MemAlloc - allocate memory from our global pool
  217. */
  218. LPVOID __cdecl MemAlloc( UINT size )
  219. {
  220. #ifdef __USECRTMALLOC
  221. return calloc( size, 1 );
  222. #else /*__USECRTMALLOC */
  223. LPBYTE lptr;
  224. DEBUG_TRACK_UPDATE_SIZE( size );
  225. #ifdef __DXGUSEALLOC
  226. #if DBG
  227. lptr = calloc( size, 1 );
  228. #else
  229. lptr = LocalAlloc( LPTR, size );
  230. #endif //DBG
  231. #else
  232. lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size );
  233. #endif //__DXGUSEALLOC
  234. DEBUG_TRACK( lptr, size );
  235. return lptr;
  236. #endif //__USECRTMALLOC
  237. } /* MemAlloc */
  238. #ifndef __DXGUSEALLOC
  239. /*
  240. * MemSize - return size of object
  241. */
  242. UINT __cdecl MemSize( LPVOID lptr )
  243. {
  244. #ifdef DEBUG
  245. if (lptr)
  246. {
  247. LPMEMTRACK pmt;
  248. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  249. pmt = lptr;
  250. return pmt->dwSize;
  251. }
  252. #endif
  253. return (UINT)HeapSize(hHeap, 0, lptr);
  254. } /* MemSize */
  255. #endif //!__DXGUSEALLOC
  256. /*
  257. * MemFree - free memory from our global pool
  258. */
  259. void MemFree( LPVOID lptr )
  260. {
  261. #ifdef __USECRTMALLOC
  262. free( lptr );
  263. #else /*__USECRTMALLOC */
  264. if( lptr != NULL )
  265. {
  266. #ifdef DEBUG
  267. {
  268. /*
  269. * get real pointer and unlink from chain
  270. */
  271. LPMEMTRACK pmt;
  272. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  273. pmt = lptr;
  274. if( pmt->dwCookie == MCOOKIE_FREE )
  275. {
  276. DPF( 1, "FREE OF FREED MEMORY! ptr=%08lx", pmt );
  277. DPF( 1, "%08lx: lAllocID=%ld dwSize=%08lx, lpAddr=%08lx",
  278. pmt, pmt->lAllocID, pmt->dwSize, pmt->lpAddr );
  279. }
  280. else if( pmt->dwCookie != MCOOKIE )
  281. {
  282. DPF( 1, "INVALID FREE! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr );
  283. DPF( 1, "%08lx: lAllocID=%ld dwSize=%08lx, lpAddr=%08lx",
  284. pmt, pmt->lAllocID, pmt->dwSize, pmt->lpAddr );
  285. }
  286. else
  287. {
  288. pmt->dwCookie = MCOOKIE_FREE;
  289. if( pmt == lpHead && pmt == lpTail )
  290. {
  291. lpHead = NULL;
  292. lpTail = NULL;
  293. }
  294. else if( pmt == lpHead )
  295. {
  296. lpHead = pmt->lpNext;
  297. lpHead->lpPrev = NULL;
  298. }
  299. else if( pmt == lpTail )
  300. {
  301. lpTail = pmt->lpPrev;
  302. lpTail->lpNext = NULL;
  303. }
  304. else
  305. {
  306. pmt->lpPrev->lpNext = pmt->lpNext;
  307. pmt->lpNext->lpPrev = pmt->lpPrev;
  308. }
  309. #ifndef NO_FILL_ON_MEMFREE
  310. {
  311. LPDWORD lpMem;
  312. DWORD dwPat;
  313. DWORD dwSize;
  314. dwSize = pmt->dwSize;
  315. lpMem = (LPDWORD)( (LPBYTE)lptr + sizeof( MEMTRACK ) );
  316. while (dwSize >= sizeof(DWORD))
  317. {
  318. *lpMem++ = FREE_MEMORY_PATTERN;
  319. dwSize -= sizeof(DWORD);
  320. }
  321. if (dwSize != 0UL)
  322. {
  323. dwPat = FREE_MEMORY_PATTERN;
  324. memcpy(lpMem, &dwPat, dwSize);
  325. }
  326. }
  327. #endif /* !NO_FILL_ON_MEMFREE */
  328. }
  329. lAllocCount--;
  330. if( lAllocCount < 0 )
  331. {
  332. DPF( 1, "Too Many Frees!\n" );
  333. }
  334. }
  335. #endif
  336. #ifdef __DXGUSEALLOC
  337. #if DBG
  338. free( lptr );
  339. #else
  340. LocalFree( lptr );
  341. #endif //DBG
  342. #else
  343. HeapFree( hHeap, 0, lptr );
  344. #endif // __DXGUSEALLOC
  345. }
  346. #endif /*__USECRTMALLOC */
  347. } /* MemFree */
  348. /*
  349. * MemReAlloc
  350. */
  351. LPVOID __cdecl MemReAlloc( LPVOID lptr, UINT size )
  352. {
  353. #ifdef __USECRTMALLOC
  354. return realloc( lptr, size );
  355. #else /* __USECRTMALLOC */
  356. LPVOID new;
  357. DEBUG_TRACK_UPDATE_SIZE( size );
  358. #ifdef DEBUG
  359. if( lptr != NULL )
  360. {
  361. LPMEMTRACK pmt;
  362. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  363. pmt = lptr;
  364. if( pmt->dwCookie != MCOOKIE )
  365. {
  366. DPF( 1, "INVALID REALLOC! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr );
  367. DPF( 1, "%08lx: lAllocID=%ld dwSize=%08lx, lpAddr=%08lx",
  368. pmt, pmt->lAllocID, pmt->dwSize, pmt->lpAddr );
  369. }
  370. }
  371. #endif
  372. #ifdef __DXGUSEALLOC
  373. #if DBG
  374. new = realloc( lptr, size );
  375. #else //DBG
  376. new = LocalReAlloc( lptr, size, LMEM_MOVEABLE|LMEM_ZEROINIT );
  377. #endif //DBG
  378. #else //__DXGUSEALLOC
  379. new = HeapReAlloc( hHeap, HEAP_ZERO_MEMORY, lptr, size );
  380. #endif //__DXGUSEALLOC
  381. #ifdef DEBUG
  382. if (new != NULL)
  383. {
  384. LPMEMTRACK pmt = new;
  385. pmt->dwSize = size - sizeof( MEMTRACK );
  386. if( lptr == (LPVOID)lpHead )
  387. lpHead = pmt;
  388. else
  389. pmt->lpPrev->lpNext = pmt;
  390. if( lptr == (LPVOID)lpTail )
  391. lpTail = pmt;
  392. else
  393. pmt->lpNext->lpPrev = pmt;
  394. new = (LPVOID) (((LPBYTE)new) + sizeof(MEMTRACK));
  395. }
  396. #endif
  397. return new;
  398. #endif /* __USECRTMALLOC */
  399. } /* MemReAlloc */
  400. /*
  401. * MemInit - initialize the heap manager
  402. */
  403. BOOL MemInit( void )
  404. {
  405. HKEY hKey = (HKEY) NULL;
  406. #ifdef __USECRTMALLOC
  407. #include <crtdbg.h>
  408. int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  409. tmp |= _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF;
  410. _CrtSetDbgFlag(tmp);
  411. #else /* __USECRTMALLOC */
  412. #ifndef __DXGUSEALLOC
  413. if( hHeap == NULL )
  414. {
  415. hHeap = HeapCreate( HEAP_SHARED, 0x2000, 0 );
  416. if( hHeap == NULL )
  417. {
  418. return FALSE;
  419. }
  420. }
  421. #endif //!__DXGUSEALLOC
  422. #ifdef DEBUG
  423. lAllocCount = 0;
  424. lAllocID = 1;
  425. lBreakOnAllocID = 0;
  426. lBreakOnMemLeak = 0;
  427. lpHead = NULL;
  428. lpTail = NULL;
  429. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey))
  430. {
  431. LONG result;
  432. DWORD dwType = REG_DWORD;
  433. DWORD dwSize = 4;
  434. DWORD value = 0;
  435. result = RegQueryValueEx(hKey, "BreakOnAllocID", NULL, &dwType,
  436. (LPBYTE)(&value), &dwSize);
  437. if (result == ERROR_SUCCESS && dwType == REG_DWORD)
  438. {
  439. lBreakOnAllocID = value;
  440. }
  441. result = RegQueryValueEx(hKey, "BreakOnMemLeak", NULL, &dwType,
  442. (LPBYTE)(&value), &dwSize);
  443. RegCloseKey(hKey);
  444. if (result == ERROR_SUCCESS && dwType == REG_DWORD)
  445. {
  446. lBreakOnMemLeak = value;
  447. }
  448. }
  449. #endif
  450. #endif /* __USECRTMALLOC */
  451. return TRUE;
  452. } /* MemInit */
  453. #ifdef DEBUG
  454. /*
  455. * MemState - finished with our heap manager
  456. */
  457. void MemState( void )
  458. {
  459. DPF( 6, "MemState" );
  460. #ifdef WIN95
  461. // Note: There is a well known leak of 8 bytes in Win9x, this is to discount it.
  462. if( lAllocCount > 1 )
  463. #else
  464. if( lAllocCount != 0 )
  465. #endif
  466. {
  467. DPF( 0, "Memory still allocated! Alloc count = %ld", lAllocCount );
  468. DPF( 0, "Current Process (pid) = %08lx", GetCurrentProcessId() );
  469. if( lBreakOnMemLeak != 0 )
  470. {
  471. DebugBreak();
  472. }
  473. }
  474. if( lpHead != NULL )
  475. {
  476. LPMEMTRACK pmt;
  477. DWORD dwTotal = 0;
  478. DWORD pidCurrent = GetCurrentProcessId();
  479. pmt = lpHead;
  480. while( pmt != NULL )
  481. {
  482. if( pidCurrent == pmt->dwPid )
  483. dwTotal += pmt->dwSize;
  484. DPF( 0, "Memory Address: %08lx lAllocID=%ld dwSize=%08lx, ReturnAddr=%08lx (pid=%08lx)",
  485. (BYTE*)pmt + sizeof(MEMTRACK), // give the address that is returned
  486. pmt->lAllocID,
  487. pmt->dwSize,
  488. pmt->lpAddr,
  489. pmt->dwPid );
  490. pmt = pmt->lpNext;
  491. }
  492. DPF ( 0, "Total Memory Unfreed From Current Process = %ld bytes", dwTotal );
  493. }
  494. } /* MemState */
  495. #endif
  496. /*
  497. * MemFini - finished with our heap manager
  498. */
  499. void MemFini( void )
  500. {
  501. #ifdef __USECRTMALLOC
  502. #else /* __USECRTMALLOC */
  503. DPF( 2, "MemFini!" );
  504. #ifdef DEBUG
  505. MemState();
  506. #endif
  507. #ifndef __DXGUSEALLOC
  508. #if defined( WIN95 ) && defined( WANT_MEM16 )
  509. freeSelectors();
  510. #endif
  511. if( hHeap )
  512. {
  513. HeapDestroy( hHeap );
  514. hHeap = NULL;
  515. }
  516. #endif //!__DXGUSEALLOC
  517. #endif /* __USECRTMALLOC */
  518. } /* MemFini */