|
|
/*==========================================================================
* * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. * * File: memalloc.c * Content: allocates memory * History: * Date By Reason * ==== == ====== * 20-jan-95 craige initial implementation * 27-feb-95 craige don't call HeapFree with NULL, it is a huge time sink * 29-mar-95 craige memory tracker * 01-apr-95 craige happy fun joy updated header file * 06-apr-95 craige made stand-alone * 22-may-95 craige added MemAlloc16 * 12-jun-95 craige added MemReAlloc * 18-jun-95 craige deadlock joy: don't take DLL csect here * 26-jul-95 toddla added MemSize and fixed MemReAlloc * 29-feb-96 colinmc added optional debugging code to blat a a specific * bit pattern over freed memory * 08-oct-96 ketand change debug message to give a total for the terminating * process * 22-dec-00 aarono use process heap in retail (whistler b#190380) * ***************************************************************************/ #undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "memalloc.h"
#include "newdpf.h"
#define FREE_MEMORY_PATTERN 0xDEADBEEFUL
#ifdef WIN95
#ifdef NOSHARED
#define HEAP_SHARED 0
#else
#define HEAP_SHARED 0x04000000 // put heap in shared memory
#endif
#else
#define HEAP_SHARED 0
#endif
static HANDLE hHeap = NULL; // handle to shared heap for this DLL
/*
* memory track struct and list */ #ifdef DEBUG
#define MCOOKIE 0xbaaabaaa
#define MCOOKIE_FREE 0xbabababa
typedef struct _MEMTRACK { DWORD dwCookie; struct _MEMTRACK FAR *lpNext; struct _MEMTRACK FAR *lpPrev; DWORD dwSize; LPVOID lpAddr; DWORD dwPid; } MEMTRACK, FAR *LPMEMTRACK;
static LPMEMTRACK lpHead; static LPMEMTRACK lpTail; static LONG lAllocCount; static LONG lBytesAlloc;
#define DEBUG_TRACK( lptr, first ) \
if( lptr == NULL ) \ { \ DPF( 1, "Alloc of size %u FAILED!", size ); \ } \ else \ { \ LPMEMTRACK pmt; \ pmt = (LPMEMTRACK) lptr; \ pmt->dwSize = size - sizeof( MEMTRACK ); \ pmt->dwCookie = MCOOKIE; \ pmt->lpAddr = _ReturnAddress(); \ pmt->dwPid = GetCurrentProcessId(); \ if( lpHead == NULL ) \ { \ lpHead = lpTail = pmt; \ } \ else \ { \ lpTail->lpNext = pmt; \ pmt->lpPrev = lpTail; \ lpTail = pmt; \ } \ lptr = (LPVOID) (((LPBYTE) lptr) + sizeof( MEMTRACK )); \ lAllocCount++; \ lBytesAlloc+=pmt->dwSize;\ { \ IN_WRITESTATS InWS; \ memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS)); \ InWS.stat_USER3=lBytesAlloc; \ DbgWriteStats(&InWS); \ } \ }
#define DEBUG_TRACK_UPDATE_SIZE( s ) s += sizeof( MEMTRACK );
#else
#define DEBUG_TRACK( lptr, first )
#define DEBUG_TRACK_UPDATE_SIZE( size )
#endif
#if defined( WIN95 ) && defined( WANT_MEM16 )
extern DWORD _stdcall MapLS( LPVOID ); // flat -> 16:16
extern void _stdcall UnMapLS( DWORD ); // unmap 16:16
typedef struct SELLIST { struct SELLIST *link; LPBYTE base; WORD sel; } SELLIST, *LPSELLIST;
static LPSELLIST lpSelList;
/*
* MemAlloc16 * * Allocate some memory, and return a 16:16 pointer to that memory * * NOTE: ASSUMES WE ARE IN THE DLL CRITICAL SECTION! */ LPVOID __cdecl MemAlloc16( UINT size, LPDWORD p16 ) { LPBYTE lptr; LPSELLIST psel; DWORD diff;
DEBUG_TRACK_UPDATE_SIZE( size ); lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size ); DEBUG_TRACK( lptr, size ); if( lptr == NULL ) { return NULL; }
/*
* try to find an existing selector that maps this area */ psel = lpSelList; while( psel != NULL ) { if( psel->base <= lptr ) { diff = lptr - psel->base; if( diff+size < 0xf000 ) { *p16 = ((DWORD)psel->sel << 16l) + diff; return lptr; } } psel = psel->link; }
/*
* no selector found, create a new one */ psel = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, sizeof( SELLIST )); if( psel == NULL ) { return NULL; } psel->sel = HIWORD( MapLS( lptr ) ); DPF( 2, "$$$$$$ New selector allocated: %04x", psel->sel ); psel->base = lptr; psel->link = lpSelList; lpSelList = psel; *p16 = ((DWORD) psel->sel) << 16l;
return lptr;
} /* MemAlloc16 */
/*
* GetPtr16 */ LPVOID GetPtr16( LPVOID ptr ) { DWORD diff; DWORD p16; LPSELLIST psel; LPBYTE lptr;
lptr = ptr;
psel = lpSelList; while( psel != NULL ) { if( psel->base <= lptr ) { diff = lptr - psel->base; if( diff <= 0xf000 ) { p16 = ((DWORD)psel->sel << 16l) + diff; return (LPVOID) p16; } } psel = psel->link; } DPF( 1, "ERROR: NO 16:16 PTR for %08lx", lptr ); return NULL;
} /* GetPtr16 */
/*
* freeSelectors */ static void freeSelectors( void ) { LPSELLIST psel; LPSELLIST link;
psel = lpSelList; while( psel != NULL ) { link = psel->link; DPF( 2, "$$$$$$ Freeing selector %04x", psel->sel ); UnMapLS( ((DWORD)psel->sel) << 16l ); HeapFree( hHeap, 0, psel ); psel = link; } lpSelList = NULL;
} /* freeSelectors */ #endif
/*
* MemAlloc - allocate memory from our global pool */ LPVOID __cdecl MemAlloc( UINT size ) { LPBYTE lptr;
DEBUG_TRACK_UPDATE_SIZE( size ); lptr = HeapAlloc( hHeap, HEAP_ZERO_MEMORY, size ); DEBUG_TRACK( lptr, size );
return lptr;
} /* MemAlloc */
/*
* MemSize - return size of object */ UINT_PTR __cdecl MemSize( LPVOID lptr ) { #ifdef DEBUG
if (lptr) { LPMEMTRACK pmt; lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK )); pmt = lptr; return pmt->dwSize; } #endif
return HeapSize(hHeap, 0, lptr);
} /* MemSize */
/*
* MemFree - free memory from our global pool */ void MemFree( LPVOID lptr ) { if( lptr != NULL ) { #ifdef DEBUG
{ /*
* get real pointer and unlink from chain */ LPMEMTRACK pmt; lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK )); pmt = lptr;
if( pmt->dwCookie == MCOOKIE_FREE ) { DPF( 1, "FREE OF FREED MEMORY! ptr=%08lx", pmt ); DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr ); DEBUG_BREAK(); } else if( pmt->dwCookie != MCOOKIE ) { DPF( 1, "INVALID FREE! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr ); DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr ); DEBUG_BREAK(); } else { pmt->dwCookie = MCOOKIE_FREE; if( pmt == lpHead && pmt == lpTail ) { lpHead = NULL; lpTail = NULL; } else if( pmt == lpHead ) { lpHead = pmt->lpNext; lpHead->lpPrev = NULL; } else if( pmt == lpTail ) { lpTail = pmt->lpPrev; lpTail->lpNext = NULL; } else { pmt->lpPrev->lpNext = pmt->lpNext; pmt->lpNext->lpPrev = pmt->lpPrev; }
#ifdef DEBUG
lBytesAlloc -= pmt->dwSize; { IN_WRITESTATS InWS; memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS)); InWS.stat_USER3=lBytesAlloc; DbgWriteStats(&InWS); } #endif
#ifdef FILL_ON_MEMFREE
{ LPDWORD lpMem; DWORD dwPat; DWORD dwSize;
dwSize = pmt->dwSize; lpMem = (LPDWORD)( (LPBYTE)lptr + sizeof( MEMTRACK ) ); while (dwSize >= sizeof(DWORD)) { *lpMem++ = FREE_MEMORY_PATTERN; dwSize -= sizeof(DWORD); } if (dwSize != 0UL) { dwPat = FREE_MEMORY_PATTERN; memcpy(lpMem, &dwPat, dwSize); } } #endif
} lAllocCount--; if( lAllocCount < 0 ) { DPF( 1, "Too Many Frees!\n" ); } } #endif
HeapFree( hHeap, 0, lptr );
}
} /* MemFree */
/*
* MemReAlloc */ LPVOID __cdecl MemReAlloc( LPVOID lptr, UINT size ) { LPVOID new;
DEBUG_TRACK_UPDATE_SIZE( size ); #ifdef DEBUG
if( lptr != NULL ) { LPMEMTRACK pmt; lptr = (LPVOID) (((LPBYTE)lptr) - sizeof( MEMTRACK )); pmt = lptr; if( pmt->dwCookie != MCOOKIE ) { DPF( 1, "INVALID REALLOC! cookie=%08lx, ptr = %08lx", pmt->dwCookie, lptr ); DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx", pmt, pmt->dwSize, pmt->lpAddr ); } } #endif
new = HeapReAlloc( hHeap, HEAP_ZERO_MEMORY, lptr, size );
#ifdef DEBUG
if (new != NULL) { LPMEMTRACK pmt = new;
lBytesAlloc -= pmt->dwSize;
pmt->dwSize = size - sizeof( MEMTRACK );
lBytesAlloc += pmt->dwSize;
{ IN_WRITESTATS InWS; memset((PVOID)&InWS,0xFF,sizeof(IN_WRITESTATS)); InWS.stat_USER3=lBytesAlloc; DbgWriteStats(&InWS); }
if( lptr == (LPVOID)lpHead ) lpHead = pmt; else pmt->lpPrev->lpNext = pmt;
if( lptr == (LPVOID)lpTail ) lpTail = pmt; else pmt->lpNext->lpPrev = pmt;
new = (LPVOID) (((LPBYTE)new) + sizeof(MEMTRACK)); } #endif
return new;
} /* MemReAlloc */
/*
* MemInit - initialize the heap manager */ BOOL MemInit( void ) { if( hHeap == NULL ) { #ifdef DEBUG
hHeap = HeapCreate( HEAP_SHARED, 0x2000, 0 ); #else
hHeap = GetProcessHeap(); #endif
if( hHeap == NULL ) { return FALSE; } } #ifdef DEBUG
lAllocCount = 0; lBytesAlloc = 0; lpHead = NULL; lpTail = NULL; #endif
return TRUE;
} /* MemInit */
#ifdef DEBUG
/*
* MemState - finished with our heap manager */ void MemState( void ) { DPF( 2, "MemState" ); if( lAllocCount != 0 ) { DPF( 1, "Memory still allocated! Alloc count = %ld", lAllocCount ); DPF( 1, "Current Process (pid) = %08lx", GetCurrentProcessId() ); } if( lpHead != NULL ) { LPMEMTRACK pmt; DWORD dwTotal = 0; DWORD pidCurrent = GetCurrentProcessId(); pmt = lpHead; while( pmt != NULL ) { if( pidCurrent == pmt->dwPid ) dwTotal += pmt->dwSize; DPF( 1, "%08lx: dwSize=%08lx, lpAddr=%08lx (pid=%08lx)", pmt, pmt->dwSize, pmt->lpAddr, pmt->dwPid ); pmt = pmt->lpNext; } DPF ( 1, "Total Memory Unfreed From Current Process = %ld bytes", dwTotal ); } } /* MemState */ #endif
/*
* MemFini - finished with our heap manager */ void MemFini( void ) { DPF( 2, "MemFini!" ); #ifdef DEBUG
MemState(); #endif
#if defined( WIN95 ) && defined( WANT_MEM16 )
freeSelectors(); #endif
if( hHeap ) { #ifdef DEBUG
HeapDestroy( hHeap ); #endif
hHeap = NULL; } } /* MemFini */
|