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.

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