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.

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