fixheap.c

来自「wince下的源代码集合打包」· C语言 代码 · 共 753 行 · 第 1/2 页

C
753
字号
/* Copyright (c) 1999-2000 Microsoft Corporation.  All rights reserved. */#include <windows.h>#include <coredll.h>#include "heap.h"#include <memory.h>// layout: (DBG = with sentinels, RET = without sentinels)//	[4 byte size in bytes not including headers, H_FREEBLOCK set if free]//	[4 byte signature set to FREESIGHEAD/ALLOCSIGHEAD in DBG, unused on 64 bit//		machines RET, not present on 32 bit machines RET]//	[n byte free or data]//	[4 byte signature set to FREESIGTAIL/ALLOCSIGTAIL in DBG, not present in RET]//	[4 byte unused on 64 bit machines in DBG, else not present]extern DWORD pagemask;extern heap ProcessHeap;_inline void INITFREEBLOCK(LPVOID p, UINT size) {	HEADPTR(p)->size = (size & H_SIZEMASK) | H_FREEBLOCK;#if HEAP_SENTINELS	HEADPTR(p)->sig = FREESIGHEAD;	TAILPTR(p)->sig = FREESIGTAIL;#endif#ifdef DEBUG	memset(HEAPTOPTR(p),0xcc,size);#endif}_inline void INITUSEDBLOCK(LPVOID p, UINT size) {	HEADPTR(p)->size = size & H_SIZEMASK;#if HEAP_SENTINELS	HEADPTR(p)->sig = ALLOCSIGHEAD;	TAILPTR(p)->sig = ALLOCSIGTAIL;#endif}_inline void INITDEADBLOCK(LPVOID p, UINT size) {	HEADPTR(p)->size = (size & H_SIZEMASK) | H_DEADBLOCK;#if HEAP_SENTINELS	HEADPTR(p)->sig = DEADSIGHEAD;	TAILPTR(p)->sig = DEADSIGTAIL;#endif}BOOL IsSigValid(pheap pHeap, LPVOID ptr, DWORD allowfree) {	if (!pHeap->pMem || ((DWORD)ptr < (DWORD)pHeap->pMem) || ((DWORD)ptr > (DWORD)pHeap->pHigh - HDRSIZE - TLRSIZE))        return FALSE;	if (!allowfree && !ISINUSE(ptr))		return FALSE;#if HEAP_SENTINELS	if (HEADPTR(ptr)->sig != (ISFREE(ptr) ? FREESIGHEAD : ISDEAD(ptr) ? DEADSIGHEAD : ALLOCSIGHEAD))		return FALSE;#endif	if ((DWORD)TAILPTR(ptr) + TLRSIZE > (DWORD)pHeap->pHigh)		return FALSE;#if HEAP_SENTINELS	if (TAILPTR(ptr)->sig != (ISFREE(ptr) ? FREESIGTAIL : ISDEAD(ptr) ? DEADSIGTAIL :ALLOCSIGTAIL))		return FALSE;#endif	return TRUE;}// Extend a free block, only through other free blocksvoid GrowFree(pheap pHeap, LPVOID ptr) {	LPVOID newptr;	DWORD growth, numnew;	growth = numnew = 0;	newptr = NEXTBLOCK(pHeap, ptr);	while ((newptr > ptr) && ISFREE(newptr)) {		growth += ITEMSIZE(newptr) + HDRSIZE + TLRSIZE;		numnew++;		newptr = NEXTBLOCK(pHeap, newptr);	}	if (growth) {		HEADPTR(ptr)->size += growth;		pHeap->dwFree += (HDRSIZE+TLRSIZE)*numnew;#ifdef DEBUG		memset(HEAPTOPTR(ptr),0xcc,ITEMSIZE(ptr));#endif	}	if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))		pHeap->dwMaxLeft = ITEMSIZE(ptr);}// Extend a free/dead block through other free/dead blocks if it will yield a free block of 'size'DWORD MakePotentialSize(pheap pHeap, LPBYTE ptr, DWORD size) {	LPBYTE ptr2 = ptr;	int deadbytes = 0, numpieces = 0, lastdead = 0, size2, maxhit;	do {		numpieces++;		if (lastdead = ISDEAD(ptr2)) {			maxhit = (ITEMSIZE(ptr2) == pHeap->dwMaxLeft);			deadbytes += ITEMSIZE(ptr2);		}		ptr2 = NEXTBLOCK(pHeap,ptr2);	} while ((ptr2 != pHeap->pMem) && !ISINUSE(ptr2) && (ptr2 < ptr + size + HDRSIZE + TLRSIZE));	if (ptr2 == pHeap->pMem)		ptr2 = pHeap->pHigh;	if (ptr + HDRSIZE + TLRSIZE + size > ptr2)		return FALSE;    pHeap->flOptions |= HEAP_IS_CHANGING_VM;	if (lastdead) {		LPBYTE tmpptr1, tmpptr2;		tmpptr1 = (LPBYTE)((DWORD)(ptr + HDRSIZE + size + TLRSIZE + HDRSIZE + pagemask) & ~pagemask);		tmpptr2 = (LPBYTE)((DWORD)(ptr2 - TLRSIZE) & ~pagemask);		if (tmpptr1 < tmpptr2) {			deadbytes -= ptr2 - TLRSIZE - tmpptr1;			size2 = ptr2 - TLRSIZE - tmpptr1;			ptr2 = tmpptr1 - HDRSIZE;		} else			lastdead = 0;	}	// since this does whole pages, it'll get the header for ptr2 if we're doing a lastdead	if (!VirtualAlloc(ptr,ptr2-ptr,MEM_COMMIT, PAGE_READWRITE)) {	    pHeap->flOptions &= ~HEAP_IS_CHANGING_VM;		return FALSE;	}	if (lastdead) {		INITDEADBLOCK(ptr2,size2);		numpieces--;		if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr2)))			pHeap->dwMaxLeft = ITEMSIZE(ptr2);		else if (maxhit)			pHeap->dwMaxLeft = 0;	}    pHeap->flOptions &= ~HEAP_IS_CHANGING_VM;	INITFREEBLOCK(ptr,ptr2-ptr-HDRSIZE-TLRSIZE);	numpieces--;	pHeap->dwCommitted += deadbytes;	pHeap->dwFree += deadbytes;    pHeap->dwFree += numpieces*(HDRSIZE+TLRSIZE);	if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr)))		pHeap->dwMaxLeft = ITEMSIZE(ptr);	return TRUE;}// Break a free block into two pieces (if enough room)void SplitFreeBlock(pheap pHeap, LPVOID ptr, UINT size) {	UINT cursize;	LPVOID ptr2;	cursize = ITEMSIZE(ptr);	if (pHeap->dwMaxLeft == cursize)		pHeap->dwMaxLeft = 0;	if (cursize - size > HDRSIZE + TLRSIZE) {		ptr2 = (LPVOID)((DWORD)ptr + HDRSIZE + TLRSIZE + size);		INITFREEBLOCK(ptr,size);		INITFREEBLOCK(ptr2,cursize-size-HDRSIZE-TLRSIZE);		// needed because of the "extension" case, since if we allowed the original free extension to be		// added, it would immediately be removed and we'd set to 0.		if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr2)))			pHeap->dwMaxLeft = ITEMSIZE(ptr2);		DEBUGCHK(pHeap->dwFree >= HDRSIZE + TLRSIZE);		pHeap->dwFree -= HDRSIZE + TLRSIZE;	}}// Shrink a block (splitting off another free block)void ShrinkBlock(pheap pHeap, LPVOID ptr, UINT size) {	UINT cursize;	LPVOID ptr2;	cursize = ITEMSIZE(ptr);	if (cursize - size > HDRSIZE + TLRSIZE) {		ptr2 = (LPVOID)((DWORD)ptr + HDRSIZE + TLRSIZE + size);		HEADPTR(ptr)->size = size;#if HEAP_SENTINELS		TAILPTR(ptr)->sig = ALLOCSIGTAIL;#endif		INITFREEBLOCK(ptr2,cursize-size-HDRSIZE-TLRSIZE);		if (pHeap->dwMaxLeft && (pHeap->dwMaxLeft < ITEMSIZE(ptr2)))			pHeap->dwMaxLeft = ITEMSIZE(ptr2);		pHeap->dwFree += cursize-size-HDRSIZE-TLRSIZE;	}}#ifdef DEBUGUINT WINAPI _HeapDump(HLOCAL hHeap) {    pheap  pHeap = (pheap) hHeap;	LPVOID ptr;	UINT retval = 0;	vaheapalloc *pvalloc;    if (!pHeap)        pHeap = &ProcessHeap;    EnterCriticalSection(&hcs);    try {		if (!pHeap->pMem) {	        DEBUGMSG(1, (TEXT("_HeapDump: Heap empty\r\n")));	        goto done;	    }		while (pHeap) {		    DEBUGMSG(1, (TEXT("flOptions:     0x%08X   pMem:    0x%08X\r\npHigh:         0x%08X   pLast:   0x%08X\r\ndwMaximumSize: 0x%08X   pCur:    0x%08X\r\ndwCommitted:   0x%08X   HDRSIZE: 0x%08X\r\ndwFree:        0x%08X   TLRSIZE: 0x%08X\r\n\r\n"),    		             pHeap->flOptions,        		         pHeap->pMem,            		     pHeap->pHigh,	                	 pHeap->dwLastCompact,		                 pHeap->dwMaximumSize,	    	             pHeap->pCur,	        	         pHeap->dwCommitted,	            	     HDRSIZE,		                 pHeap->dwFree,		                 TLRSIZE));			ptr = pHeap->pMem;			do {				if (!IsSigValid(pHeap,ptr,1)) {					retval = 1;					goto done;				}#if HEAP_SENTINELS		        DEBUGMSG(1, (TEXT("0x%08X %s size: 0x%08X sig: 0x%08X\r\n"),	    	             ptr, ISFREE(ptr) ? TEXT("FREEBLOCK") : ISDEAD(ptr) ? TEXT("DEADBLOCK") : TEXT("USEDBLOCK"),	        	         ITEMSIZE(ptr), HEADPTR(ptr)->sig));		        DEBUGMSG(1, (TEXT("0x%08X                            sig: 0x%08X\r\n"),	    	             TAILPTR(ptr), TAILPTR(ptr)->sig));#else		        DEBUGMSG(1, (TEXT("0x%08X %s size: 0x%08X\r\n"),	    	             ptr, ISFREE(ptr) ? TEXT("FREEBLOCK") : ISDEAD(ptr) ? TEXT("DEADBLOCK") :TEXT("USEDBLOCK"),	        	         ITEMSIZE(ptr)));#endif			} while ((ptr = NEXTBLOCK(pHeap, ptr)) != pHeap->pMem);			for (pvalloc = pHeap->pVallocs; pvalloc; pvalloc = pvalloc->pnext)				DEBUGMSG(1,(TEXT("Extended block at 0x%8.8lx, length 0x%8.8lx\r\n"),pvalloc->pBase,pvalloc->dwSize));			pHeap = pHeap->pGrowthHeap;		}	    DEBUGMSG(1, (TEXT("-----------------------------------------------------\r\n")));done:		;	} except (EXCEPTION_EXECUTE_HANDLER) {		retval = 1;	}    LeaveCriticalSection(&hcs);	return retval;}#endifBOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) {	BOOL retval = FALSE;	LPVOID ptr, ptr2;	pheap pHeap;	vaheapalloc *pvalloc;    if (dwFlags & ~HEAP_NO_SERIALIZE) {	    SetLastError(ERROR_INVALID_PARAMETER);		return FALSE;    }	EnterCriticalSection(&hcs);	try {		if (lpMem) {			ptr = PTRTOHEAP(lpMem);			for (pHeap = (pheap)hHeap; pHeap; pHeap = pHeap->pGrowthHeap) {				 if ((ptr >= pHeap->pMem) && (ptr < pHeap->pHigh)) {				 	retval = IsSigValid(pHeap,ptr,0);				 	goto done;				}				for (pvalloc = pHeap->pVallocs; pvalloc; pvalloc = pvalloc->pnext) {					if (pvalloc->pBase == lpMem) {						if (!((DWORD)pvalloc->pBase & 0xffff) && (pvalloc->dwSize >= CE_VALLOC_MINSIZE))							retval = TRUE;						goto done;					}				}			}		} else {			for (pHeap = (pheap)hHeap; pHeap; pHeap = pHeap->pGrowthHeap) {				if (ptr = pHeap->pMem) {					do {						if (!IsSigValid(pHeap,ptr,1))							goto done;						ptr2 = (LPVOID)((DWORD)ptr + HDRSIZE + ITEMSIZE(ptr) + TLRSIZE);						if (ptr2 <= ptr)							goto done;					} while ((ptr = ptr2) != pHeap->pHigh);				}				for (pvalloc = pHeap->pVallocs; pvalloc; pvalloc = pvalloc->pnext) {					if (((DWORD)pvalloc->pBase & 0xffff) || (pvalloc->dwSize < CE_VALLOC_MINSIZE))						goto done;				}			}			retval = TRUE;		}done:		;	} except (EXCEPTION_EXECUTE_HANDLER) {		retval = FALSE;	}	LeaveCriticalSection(&hcs);#ifdef DEBUG	if (!retval)		_HeapDump(hHeap);#endif	return retval;}// Initialize a heapBOOL SetupFixedHeap(pheap pHeap) {	LPVOID pMem;	if (!(pMem = VirtualAlloc(NULL,pHeap->dwMaximumSize,MEM_RESERVE,PAGE_NOACCESS)))        return FALSE;	pHeap->dwCommitted = pagemask + 1;    if (!VirtualAlloc(pMem,pHeap->dwCommitted, MEM_COMMIT, PAGE_READWRITE)) {    	VirtualFree(pMem,0,MEM_RELEASE);		return FALSE;	}	DEBUGCHK(pHeap->dwCommitted >= HDRSIZE + TLRSIZE);	pHeap->dwFree = pHeap->dwCommitted - HDRSIZE - TLRSIZE;	pHeap->pHigh = (LPVOID)((LPBYTE)pMem + pHeap->dwCommitted);	INITFREEBLOCK(pMem,pHeap->dwFree);	pHeap->pCur = pMem;	pHeap->pMem = pMem;	// heap is now initialized - this must come LAST!	pHeap->dwMaxLeft = ITEMSIZE(pHeap->pCur);	return TRUE;}LPBYTE InitSharedHeap(LPBYTE pMem, DWORD size, DWORD reserve) {	LPBYTE pReserved, pData;	pheap pHeap;	LPVOID pAlloc;	pReserved = pMem + ((sizeof(heap)+ALIGNMASK)&~ALIGNMASK);	if (size) {	    pAlloc = VirtualAlloc(pMem,pagemask+1, MEM_COMMIT, PAGE_READWRITE);    	DEBUGCHK(pAlloc == pMem);		pHeap = (pheap)pMem;		pData = pReserved + ((reserve+ALIGNMASK)&~ALIGNMASK);		size -= (pData - pMem);		size &= ~ALIGNMASK;		pHeap->dwCommitted   = pagemask + 1 - (pData - pMem);		pHeap->pVallocs      = 0;		pHeap->pGrowthHeap   = 0;	    pHeap->flOptions     = HEAP_IS_SHARED;	    pHeap->dwMaximumSize = size;	    pHeap->pMem          = pData;	    pHeap->pCur          = pData;	    pHeap->pHigh         = (LPVOID)((LPBYTE)pData+pHeap->dwCommitted);		DEBUGCHK(pHeap->dwCommitted >= HDRSIZE-TLRSIZE);	    pHeap->dwFree        = pHeap->dwCommitted-HDRSIZE-TLRSIZE;	    pHeap->dwLastCompact = 0;		INITFREEBLOCK(pData,pHeap->dwFree);	}	return pReserved;}// Get size of heap blockDWORD FixedHeapSize(pheap pHeap, LPVOID ptr) {	LPVOID ptr2;	vaheapalloc *pva;	pheap pTrav;	EnterCriticalSection(&hcs);	ptr2 = PTRTOHEAP(ptr);	for (pTrav = pHeap; pTrav; pTrav = pTrav->pGrowthHeap) {		if (pTrav->pMem && IsSigValid(pTrav,ptr2,0)) {			LeaveCriticalSection(&hcs);			return ITEMSIZE(ptr2);		}	}	for (pva = pHeap->pVallocs; pva; pva = pva->pnext)		if (pva->pBase == ptr) {			LeaveCriticalSection(&hcs);			return pva->dwSize;		}	LeaveCriticalSection(&hcs);	return (DWORD)-1;}// Free a heap blockBOOL FixedHeapFree(pheap pHeap, LPVOID ptr) {	LPVOID ptr2;	vaheapalloc *pva, *pvaprev;	pheap pTrav;	ptr2 = PTRTOHEAP(ptr);	for (pTrav = pHeap; pTrav; pTrav = pTrav->pGrowthHeap) {		if (pTrav->pMem && IsSigValid(pTrav,ptr2,0)) {			pTrav->dwFree += ITEMSIZE(ptr2);			INITFREEBLOCK(ptr2,ITEMSIZE(ptr2));			GrowFree(pTrav,ptr2);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?