📄 heap.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include <windows.h>
#include <coredll.h>
#include "heap.h"
#include <celogcoredll.h>
#include "lmemdebug.h"
// Make sure that no macro are redirecting LocalAlloc & HeapAlloc
#undef LocalAlloc
#undef HeapAlloc
#ifndef FREE_POINTER_AT_LAST_FREE
#define FREE_POINTER_AT_LAST_FREE
#endif
#ifdef MEMTRACKING
DWORD dwHeapMemType;
#endif
#define PAGE_SIZE (UserKInfo[KINX_PAGESIZE])
#define HEAP_MAX_ALLOC 0x40000000 // Maximum allocation request is 1GB.
DWORD PageMask;
LPVOID PSlot; // Address of the current process's "memory slot"
HANDLE hProcessHeap;
pheap phpListAll;
CRITICAL_SECTION csHeapList;
#ifdef HEAP_STATISTICS
#define NUM_ALLOC_BUCKETS 64
#define BUCKET_VIRTUAL (NUM_ALLOC_BUCKETS - 1)
#define BUCKET_LARGE (NUM_ALLOC_BUCKETS - 2)
LONG lNumAllocs[NUM_ALLOC_BUCKETS];
#endif
PFN_HeapCreate ptrHeapCreate = Int_HeapCreate;
PFN_HeapDestroy ptrHeapDestroy = Int_HeapDestroy;
PFN_HeapAlloc ptrHeapAlloc = Int_HeapAlloc;
PFN_HeapAllocTrace ptrHeapAllocTrace;
PFN_HeapReAlloc ptrHeapReAlloc = Int_HeapReAlloc;
PFN_HeapSize ptrHeapSize = Int_HeapSize;
PFN_HeapFree ptrHeapFree = Int_HeapFree;
extern PFN_CloseHandle v_pfnCloseHandle;
extern PFN_CreateEventW v_pfnCreateEventW;
extern PFN_LMEMAddTrackedItem v_pfnLMEMAddTrackedItem;
extern PFN_LMEMRemoveTrackedItem v_pfnLMEMRemoveTrackedItem;
extern PFN_SetAllocAdditionalData v_pfnSetAllocAdditionalData;
static LONG fFullyCompacted;
BOOL WINAPI LMemInit(void)
{
HMODULE hLMemDebug;
FARPROC ptrProc;
PageMask = UserKInfo[KINX_PAGESIZE] - 1;
DEBUGMSG(DBGFIXHP, (L"LMemInit\r\n"));
// Uncomment the line below for "mapped heaps"
PSlot = (char*)MapPtrUnsecure(&PSlot, GetCurrentProcess()) - (DWORD)&PSlot;
// Check to see if there is a LMemDebug library.
hLMemDebug = (HMODULE)LoadDriver(LMEMDEBUG_DLL);
if (NULL != hLMemDebug) {
RETAILMSG (1, (TEXT("Loaded LMemDebug in process\r\n")));
// Fetch the debug alloc functions.
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapCreate"));
if (ptrProc) {
ptrHeapCreate = (PFN_HeapCreate)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapDestroy"));
if (ptrProc) {
ptrHeapDestroy = (PFN_HeapDestroy)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapAlloc"));
if (ptrProc) {
ptrHeapAlloc = (PFN_HeapAlloc)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapAllocTrace"));
if (ptrProc) {
ptrHeapAllocTrace = (PFN_HeapAllocTrace)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapReAlloc"));
if (ptrProc) {
ptrHeapReAlloc = (PFN_HeapReAlloc)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapFree"));
if (ptrProc) {
ptrHeapFree = (PFN_HeapFree)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("HeapSize"));
if (ptrProc) {
ptrHeapSize = (PFN_HeapSize)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("CloseHandle"));
if (ptrProc) {
v_pfnCloseHandle = (PFN_CloseHandle)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("CreateEventW"));
if (ptrProc) {
v_pfnCreateEventW = (PFN_CreateEventW)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("LMEMAddTrackedItem"));
if (ptrProc) {
v_pfnLMEMAddTrackedItem = (PFN_LMEMAddTrackedItem)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("LMEMRemoveTrackedItem"));
if (ptrProc) {
v_pfnLMEMRemoveTrackedItem = (PFN_LMEMRemoveTrackedItem)ptrProc;
}
ptrProc = GetProcAddress(hLMemDebug, TEXT("SetAllocAdditionalData"));
if (ptrProc) {
v_pfnSetAllocAdditionalData = (PFN_SetAllocAdditionalData)ptrProc;
}
}
#ifdef MEMTRACKING
dwHeapMemType = RegisterTrackedItem(L"Heaps");
#endif
InitializeCriticalSection(&csHeapList);
if ((hProcessHeap = HeapCreate(0, 0, 0)) == NULL)
return FALSE;
((pheap)hProcessHeap)->flOptions |= HEAP_IS_PROC_HEAP;
#ifdef MEMTRACKING
((pheap)hProcessHeap)->dwMemType = RegisterTrackedItem(L"Local Memory");
#endif
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CELOG_HeapCreate(HEAP_IS_PROC_HEAP, 0, CE_FIXED_HEAP_MAXSIZE, hProcessHeap);
}
DEBUGMSG(DBGFIXHP, (L" LMemInit: Done PSlot = %08x hProcessHeap = %08x\r\n", PSlot, hProcessHeap));
#ifdef HEAP_STATISTICS
NKDbgPrintfW (L"Heap Statistics at 0x%08X", (DWORD) lNumAllocs | (DWORD) PSlot);
#endif
return TRUE;
}
void LMemDeInit (void)
{
// restore everything back to default since LMEMDebug has already been freed
ptrHeapCreate = Int_HeapCreate;
ptrHeapDestroy = Int_HeapDestroy;
ptrHeapAlloc = Int_HeapAlloc;
ptrHeapAllocTrace;
ptrHeapReAlloc = Int_HeapReAlloc;
ptrHeapSize = Int_HeapSize;
ptrHeapFree = Int_HeapFree;
v_pfnCloseHandle = NULL;
v_pfnCreateEventW = NULL;
v_pfnLMEMAddTrackedItem = NULL;
v_pfnLMEMRemoveTrackedItem = NULL;
v_pfnSetAllocAdditionalData = NULL;
}
#if defined(MEMTRACKING) && defined(MEM_ACCOUNT)
void TrackerCallback (DWORD dwFlags, DWORD dwType, HANDLE hItem, DWORD dwProc, BOOL fDeleted,
DWORD dwSize, DWORD dw1, DWORD dw2) {
PBYTE p = (PBYTE)hItem;
if (!fDeleted && *(int*)p == 0x8482906) {
NKDbgPrintfW (L"%a %i", p+4, *(int*)(p+20));
if (!memcmp (p+4, "String", 7))
NKDbgPrintfW (L" :\"%s\"", p+24);
}
NKDbgPrintfW (L"\r\n");
}
#define TCB TrackerCallback
#else
#define TCB NULL
#endif
/*
@doc BOTH EXTERNAL
@func HLOCAL | LocalAlloc | Allocates a block of memory from the local heap
@parm UINT | uFlags | flags for alloc operation
@parm UINT | uBytes | desired size of block
@comm Only fixed memory is supported, thus LMEM_MOVEABLE is invalid.
*/
HLOCAL WINAPI LocalAlloc(UINT uFlags, UINT uBytes) {
LPVOID p;
if(uFlags & ~LMEM_VALID_FLAGS) {
DEBUGMSG(DBGLMEM, (L" LocalAlloc %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n",uBytes,uFlags,0));
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
p = ptrHeapAlloc(hProcessHeap, (uFlags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0, uBytes);
DEBUGMSG(DBGLMEM, (L" LocalAlloc %8.8lx %8.8lx ==> %8.8lx [%8.8lx]\r\n",uBytes,uFlags,p,Int_HeapSize(hProcessHeap,0,p)));
return (HLOCAL)p;
}
HLOCAL WINAPI LocalAllocTrace(UINT uFlags, UINT uBytes, UINT dwLineNum, PCHAR szFilename) {
LPVOID p;
if(uFlags & ~LMEM_VALID_FLAGS) {
DEBUGMSG(DBGLMEM, (L" LocalAllocTrace %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n",uBytes,uFlags,0));
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
p = HeapAllocTrace(hProcessHeap, (uFlags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0, uBytes, dwLineNum, szFilename);
DEBUGMSG(DBGLMEM, (L" LocalAllocTrace %8.8lx %8.8lx ==> %8.8lx [%8.8lx]\r\n",uBytes,uFlags,p,Int_HeapSize(hProcessHeap,0,p)));
return (HLOCAL)p;
}
/*
@doc BOTH EXTERNAL
@func HLOCAL | LocalRealloc | Realloc's a LocalAlloc'ed block of memory
@parm HLOCAL | hMem | handle of local memory object to realloc
@parm UINT | uBytes | desired new size of block
@parm UINT | uFlags | flags for realloc operation
@comm Follows the Win32 reference description without restrictions
or modifications.
*/
HLOCAL WINAPI LocalReAlloc(HLOCAL hMem, UINT uBytes, UINT uFlags) {
LPVOID retval;
UINT newflags;
if((uFlags & ~(LMEM_VALID_FLAGS | LMEM_MODIFY )) ||
((uFlags & LMEM_DISCARDABLE) && !(uFlags & LMEM_MODIFY))) {
DEBUGMSG(DBGLMEM, (L" LocalRealloc %8.8lx %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n",hMem,uBytes,uFlags,0));
SetLastError(ERROR_INVALID_PARAMETER);
return(NULL);
}
newflags = ((uFlags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0) | ((uFlags & LMEM_MOVEABLE) ? 0 : HEAP_REALLOC_IN_PLACE_ONLY);
retval = HeapReAlloc(hProcessHeap, newflags, hMem, uBytes);
DEBUGMSG(DBGLMEM, (L" LocalRealloc %8.8lx %8.8lx %8.8lx ==> %8.8lx [%8.8lx]\r\n",hMem,uBytes,uFlags,retval,Int_HeapSize(hProcessHeap,0,retval)));
return (HLOCAL)retval;
}
/*
@doc BOTH EXTERNAL
@func UINT | LocalSize | Returns the size of a LocalAlloc'ed block of memory
@parm HLOCAL | hMem | handle of local memory object to get size of
@comm Follows the Win32 reference description without restrictions
or modifications.
*/
UINT WINAPI LocalSize(HLOCAL hMem) {
UINT retval;
if ((retval = ptrHeapSize(hProcessHeap,0,hMem)) == (DWORD)-1)
retval = 0;
DEBUGMSG(DBGLMEM, (L" LocalSize %8.8lx ==> %8.8lx\r\n",hMem,retval));
return retval;
}
/*
@doc BOTH EXTERNAL
@func HLOCAL | LocalFree | Frees a LocalAlloc'ed block of memory
@parm HLOCAL | hMem | handle of local memory object to free
@comm Follows the Win32 reference description without restrictions
or modifications.
*/
HLOCAL WINAPI LocalFree(HLOCAL hMem) {
HLOCAL retval;
if (retval = (!hMem || ptrHeapFree(hProcessHeap,0,(LPVOID)hMem)) ? NULL : hMem)
SetLastError(ERROR_INVALID_PARAMETER);
DEBUGMSG(DBGLMEM, (L" LocalFree %8.8lx ==> %8.8lx\r\n",hMem,retval));
return retval;
}
#if HEAP_SENTINELS
/** CheckSentinels() - verify allocated heap block sentinels
*/
BOOL CheckSentinels(pitem pit, BOOL bStopOnErr)
{
int chSig = 0xA5;
PBYTE pTail = (char*)(pit+1) + pit->cbTrueSize;
int cbTail = (pit->size&~1) - sizeof(item) - pit->cbTrueSize;
if (pit->dwSig != ALLOCSIGHEAD) {
RETAILMSG(1, (L"CheckSentinels: Bad head signature @0x%08X --> 0x%08X SHDB 0x%08X\r\n",
pit, pit->dwSig, ALLOCSIGHEAD));
#ifdef DEBUG
if (bStopOnErr)
DebugBreak();
#endif
return FALSE;
}
while (cbTail--) {
if (*pTail != chSig) {
RETAILMSG(1, (L"CheckSentinels: Bad tail signature item: 0x%08X @0x%08X -> 0x%02x SHDB 0x%02x\r\n",
pit, pTail, *pTail, chSig));
#ifdef DEBUG
if (bStopOnErr)
DebugBreak();
#endif
return FALSE;
}
++pTail;
chSig = chSig+1 & 0xFF;
}
return TRUE;
}
/** SetSentinels() - set allocated heap block sentinels
*/
void SetSentinels(pitem pit, int cbRequest)
{
int chSig = 0xA5;
int cbTail = (pit->size&~1) - cbRequest - sizeof(item);
PBYTE pTail = (PBYTE)(pit+1) + cbRequest;
DEBUGCHK((int)(pit->size - sizeof(pitem)) >= cbRequest+cbTail);
pit->cbTrueSize = cbRequest;
pit->dwSig = ALLOCSIGHEAD;
while (cbTail--)
*pTail++ = chSig++;
}
/** CheckFreeSentinels() - verify free heap block sentinels
*/
BOOL CheckFreeSentinels(pitem pit, BOOL bStopOnErr)
{
PBYTE pTail = (PBYTE)(pit+1);
int cbTail = sizeof(item) - pit->size;
if (pit->dwSig != FREESIGHEAD) {
RETAILMSG(1, (L"CheckFreeSentinels: Bad head signature @0x%08X --> 0x%08X SHDB 0x%08X\r\n",
pit, pit->dwSig, FREESIGHEAD));
#ifdef DEBUG
if (bStopOnErr)
DebugBreak();
#endif
return FALSE;
}
if (pit->size > -(int)sizeof(item) || (pit->size & ALIGNBYTES-1) != 0) {
RETAILMSG(1, (L"CheckFreeSentinels: Bogus size @0x%08X --> 0x%08X \r\n", pit, pit->size));
#ifdef DEBUG
if (bStopOnErr)
DebugBreak();
#endif
return FALSE;
}
return TRUE;
}
/** SetSentinels() - set heap block sentinels
*/
void SetFreeSentinels(pitem pit)
{
PBYTE pTail = (PBYTE)(pit+1);
int cbTail = -pit->size - sizeof(item);
DEBUGCHK(pit->size <= -(int)sizeof(item) && (pit->size & ALIGNBYTES-1) == 0);
pit->dwSig = FREESIGHEAD;
pit->cbTrueSize = cbTail;
}
#endif
static LPVOID AllocMemShare (LPVOID pAddr, DWORD cbSize, DWORD fdwAction, LPDWORD pdwUnused)
{
return CeVirtualSharedAlloc ((MEM_RESERVE & fdwAction)? NULL : pAddr, cbSize, fdwAction);
}
static LPVOID AllocMemVirt (LPVOID pAddr, DWORD cbSize, DWORD fdwAction, LPDWORD pdwUnused)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -