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.

461 lines
9.5 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. #ifdef WIN95
  32. #ifdef NOSHARED
  33. #define HEAP_SHARED 0
  34. #else
  35. #define HEAP_SHARED 0x04000000 // put heap in shared memory
  36. #endif
  37. #else
  38. #define HEAP_SHARED 0
  39. #endif
  40. static HANDLE hHeap = NULL; // handle to shared heap for this DLL
  41. /*
  42. * memory track struct and list
  43. */
  44. #ifdef DEBUG
  45. #define MCOOKIE 0xbaaabaaa
  46. #define MCOOKIE_FREE 0xbabababa
  47. typedef struct _MEMTRACK
  48. {
  49. DWORD dwCookie;
  50. struct _MEMTRACK FAR *lpNext;
  51. struct _MEMTRACK FAR *lpPrev;
  52. DWORD dwSize;
  53. LPVOID lpAddr;
  54. DWORD dwPid;
  55. } MEMTRACK, FAR *LPMEMTRACK;
  56. static LPMEMTRACK lpHead;
  57. static LPMEMTRACK lpTail;
  58. static LONG lAllocCount;
  59. #define DEBUG_TRACK( lptr, first ) \
  60. if( lptr == NULL ) \
  61. { \
  62. DPF( 1, "Alloc of size %u FAILED!", size ); \
  63. } \
  64. else \
  65. { \
  66. LPMEMTRACK pmt; \
  67. pmt = (LPMEMTRACK) lptr; \
  68. pmt->dwSize = size - sizeof( MEMTRACK ); \
  69. pmt->dwCookie = MCOOKIE; \
  70. pmt->lpAddr = _ReturnAddress(); \
  71. pmt->dwPid = GetCurrentProcessId(); \
  72. if( lpHead == NULL ) \
  73. { \
  74. lpHead = lpTail = pmt; \
  75. } \
  76. else \
  77. { \
  78. lpTail->lpNext = pmt; \
  79. pmt->lpPrev = lpTail; \
  80. lpTail = pmt; \
  81. } \
  82. lptr = (LPVOID) (((LPBYTE) lptr) + sizeof( MEMTRACK )); \
  83. lAllocCount++; \
  84. }
  85. #define DEBUG_TRACK_UPDATE_SIZE( s ) s += sizeof( MEMTRACK );
  86. #else
  87. #define DEBUG_TRACK( lptr, first )
  88. #define DEBUG_TRACK_UPDATE_SIZE( size )
  89. #endif
  90. #if defined( WIN95 ) && defined( WANT_MEM16 )
  91. extern DWORD _stdcall MapLS( LPVOID ); // flat -> 16:16
  92. extern void _stdcall UnMapLS( DWORD ); // unmap 16:16
  93. typedef struct SELLIST {
  94. struct SELLIST *link;
  95. LPBYTE base;
  96. WORD sel;
  97. } SELLIST, *LPSELLIST;
  98. static LPSELLIST lpSelList;
  99. /*
  100. * MemAlloc16
  101. *
  102. * Allocate some memory, and return a 16:16 pointer to that memory
  103. *
  104. * NOTE: ASSUMES WE ARE IN THE DLL CRITICAL SECTION!
  105. */
  106. LPVOID __cdecl MemAlloc16( UINT size, LPDWORD p16 )
  107. {
  108. LPBYTE lptr;
  109. LPSELLIST psel;
  110. DWORD diff;
  111. DEBUG_TRACK_UPDATE_SIZE( size );
  112. lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size );
  113. DEBUG_TRACK( lptr, size );
  114. if( lptr == NULL )
  115. {
  116. return NULL;
  117. }
  118. /*
  119. * try to find an existing selector that maps this area
  120. */
  121. psel = lpSelList;
  122. while( psel != NULL )
  123. {
  124. if( psel->base <= lptr )
  125. {
  126. diff = lptr - psel->base;
  127. if( diff+size < 0xf000 )
  128. {
  129. *p16 = ((DWORD)psel->sel << 16l) + diff;
  130. return lptr;
  131. }
  132. }
  133. psel = psel->link;
  134. }
  135. /*
  136. * no selector found, create a new one
  137. */
  138. psel = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, sizeof( SELLIST ));
  139. if( psel == NULL )
  140. {
  141. return NULL;
  142. }
  143. psel->sel = HIWORD( MapLS( lptr ) );
  144. DPF( 2, "$$$$$$ New selector allocated: %04x", psel->sel );
  145. psel->base = lptr;
  146. psel->link = lpSelList;
  147. lpSelList = psel;
  148. *p16 = ((DWORD) psel->sel) << 16l;
  149. return lptr;
  150. } /* MemAlloc16 */
  151. /*
  152. * GetPtr16
  153. */
  154. LPVOID GetPtr16( LPVOID ptr )
  155. {
  156. DWORD diff;
  157. DWORD p16;
  158. LPSELLIST psel;
  159. LPBYTE lptr;
  160. lptr = ptr;
  161. psel = lpSelList;
  162. while( psel != NULL )
  163. {
  164. if( psel->base <= lptr )
  165. {
  166. diff = lptr - psel->base;
  167. if( diff <= 0xf000 )
  168. {
  169. p16 = ((DWORD)psel->sel << 16l) + diff;
  170. return (LPVOID) p16;
  171. }
  172. }
  173. psel = psel->link;
  174. }
  175. DPF( 1, "ERROR: NO 16:16 PTR for %08lx", lptr );
  176. return NULL;
  177. } /* GetPtr16 */
  178. /*
  179. * freeSelectors
  180. */
  181. static void freeSelectors( void )
  182. {
  183. LPSELLIST psel;
  184. LPSELLIST link;
  185. psel = lpSelList;
  186. while( psel != NULL )
  187. {
  188. link = psel->link;
  189. DPF( 2, "$$$$$$ Freeing selector %04x", psel->sel );
  190. UnMapLS( ((DWORD)psel->sel) << 16l );
  191. HeapFree( hHeap, 0, psel );
  192. psel = link;
  193. }
  194. lpSelList = NULL;
  195. } /* freeSelectors */
  196. #endif
  197. /*
  198. * MemAlloc - allocate memory from our global pool
  199. */
  200. LPVOID __cdecl MemAlloc( UINT size )
  201. {
  202. LPBYTE lptr;
  203. DEBUG_TRACK_UPDATE_SIZE( size );
  204. lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size );
  205. DEBUG_TRACK( lptr, size );
  206. return (LPVOID)lptr;
  207. } /* MemAlloc */
  208. /*
  209. * MemSize - return size of object
  210. */
  211. SIZE_T __cdecl MemSize( LPVOID lptr )
  212. {
  213. #ifdef DEBUG
  214. if (lptr)
  215. {
  216. LPMEMTRACK pmt;
  217. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  218. pmt = lptr;
  219. return pmt->dwSize;
  220. }
  221. #endif
  222. return HeapSize(hHeap, 0, lptr);
  223. } /* MemSize */
  224. /*
  225. * MemFree - free memory from our global pool
  226. */
  227. void MemFree( LPVOID lptr )
  228. {
  229. if( lptr != NULL )
  230. {
  231. #ifdef DEBUG
  232. {
  233. /*
  234. * get real pointer and unlink from chain
  235. */
  236. LPMEMTRACK pmt;
  237. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  238. pmt = lptr;
  239. if( pmt->dwCookie == MCOOKIE_FREE )
  240. {
  241. DPF( 1, "FREE OF FREED MEMORY! ptr=%08lx", pmt );
  242. DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr );
  243. }
  244. else if( pmt->dwCookie != MCOOKIE )
  245. {
  246. DPF( 1, "INVALID FREE! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr );
  247. DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr );
  248. }
  249. else
  250. {
  251. pmt->dwCookie = MCOOKIE_FREE;
  252. if( pmt == lpHead && pmt == lpTail )
  253. {
  254. lpHead = NULL;
  255. lpTail = NULL;
  256. }
  257. else if( pmt == lpHead )
  258. {
  259. lpHead = pmt->lpNext;
  260. lpHead->lpPrev = NULL;
  261. }
  262. else if( pmt == lpTail )
  263. {
  264. lpTail = pmt->lpPrev;
  265. lpTail->lpNext = NULL;
  266. }
  267. else
  268. {
  269. pmt->lpPrev->lpNext = pmt->lpNext;
  270. pmt->lpNext->lpPrev = pmt->lpPrev;
  271. }
  272. #ifdef FILL_ON_MEMFREE
  273. {
  274. LPDWORD lpMem;
  275. DWORD dwPat;
  276. DWORD dwSize;
  277. dwSize = pmt->dwSize;
  278. lpMem = (LPDWORD)( (LPBYTE)lptr + sizeof( MEMTRACK ) );
  279. while (dwSize >= sizeof(DWORD))
  280. {
  281. *lpMem++ = FREE_MEMORY_PATTERN;
  282. dwSize -= sizeof(DWORD);
  283. }
  284. if (dwSize != 0UL)
  285. {
  286. dwPat = FREE_MEMORY_PATTERN;
  287. memcpy(lpMem, &dwPat, dwSize);
  288. }
  289. }
  290. #endif
  291. }
  292. lAllocCount--;
  293. if( lAllocCount < 0 )
  294. {
  295. DPF( 1, "Too Many Frees!\n" );
  296. }
  297. }
  298. #endif
  299. HeapFree( hHeap, 0, lptr );
  300. }
  301. } /* MemFree */
  302. /*
  303. * MemReAlloc
  304. */
  305. LPVOID __cdecl MemReAlloc( LPVOID lptr, UINT size )
  306. {
  307. LPVOID new;
  308. DEBUG_TRACK_UPDATE_SIZE( size );
  309. #ifdef DEBUG
  310. if( lptr != NULL )
  311. {
  312. LPMEMTRACK pmt;
  313. lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK ));
  314. pmt = lptr;
  315. if( pmt->dwCookie != MCOOKIE )
  316. {
  317. DPF( 1, "INVALID REALLOC! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr );
  318. DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr );
  319. }
  320. }
  321. #endif
  322. new = HeapReAlloc( hHeap, HEAP_ZERO_MEMORY, lptr, size );
  323. #ifdef DEBUG
  324. if (new != NULL)
  325. {
  326. LPMEMTRACK pmt = new;
  327. pmt->dwSize = size - sizeof( MEMTRACK );
  328. if( lptr == (LPVOID)lpHead )
  329. lpHead = pmt;
  330. else
  331. pmt->lpPrev->lpNext = pmt;
  332. if( lptr == (LPVOID)lpTail )
  333. lpTail = pmt;
  334. else
  335. pmt->lpNext->lpPrev = pmt;
  336. new = (LPVOID) (((LPBYTE)new) + sizeof(MEMTRACK));
  337. }
  338. #endif
  339. return new;
  340. } /* MemReAlloc */
  341. /*
  342. * MemInit - initialize the heap manager
  343. */
  344. BOOL MemInit( void )
  345. {
  346. if( hHeap == NULL )
  347. {
  348. hHeap = HeapCreate( HEAP_SHARED, 0x2000, 0 );
  349. if( hHeap == NULL )
  350. {
  351. return FALSE;
  352. }
  353. }
  354. #ifdef DEBUG
  355. lAllocCount = 0;
  356. lpHead = NULL;
  357. lpTail = NULL;
  358. #endif
  359. return TRUE;
  360. } /* MemInit */
  361. #ifdef DEBUG
  362. /*
  363. * MemState - finished with our heap manager
  364. */
  365. void MemState( void )
  366. {
  367. DPF( 2, "MemState" );
  368. if( lAllocCount != 0 )
  369. {
  370. DPF( 1, "Memory still allocated! Alloc count = %ld", lAllocCount );
  371. DPF( 1, "Current Process (pid) = %08lx", GetCurrentProcessId() );
  372. }
  373. if( lpHead != NULL )
  374. {
  375. LPMEMTRACK pmt;
  376. DWORD dwTotal = 0;
  377. DWORD pidCurrent = GetCurrentProcessId();
  378. pmt = lpHead;
  379. while( pmt != NULL )
  380. {
  381. if( pidCurrent == pmt->dwPid )
  382. dwTotal += pmt->dwSize;
  383. DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx (pid=%08lx)", pmt, pmt->dwSize, pmt->lpAddr, pmt->dwPid );
  384. pmt = pmt->lpNext;
  385. }
  386. DPF ( 1, "Total Memory Unfreed From Current Process = %ld bytes", dwTotal );
  387. }
  388. } /* MemState */
  389. #endif
  390. /*
  391. * MemFini - finished with our heap manager
  392. */
  393. void MemFini( void )
  394. {
  395. DPF( 2, "MemFini!" );
  396. #ifdef DEBUG
  397. MemState();
  398. #endif
  399. #if defined( WIN95 ) && defined( WANT_MEM16 )
  400. freeSelectors();
  401. #endif
  402. if( hHeap )
  403. {
  404. HeapDestroy( hHeap );
  405. hHeap = NULL;
  406. }
  407. } /* MemFini */