www.pudn.com > He4Hook215b6.rar > KMemoryManager.cpp
//
// Данный код можно использовать на IRQL <= DISPATCH_LEVEL,
// если __KHEAP_LOCK_MUTEX не определен, иначе IRQL == PASSIVE_LEVEL
//
#include "KMemoryManager.h"
//
// нижеследующие ф-ии _только_ для внутреннего использования MemoryManager-ом.
//
static PMEMORY_BLOCK KHeapGetFreeBlock(KHEAP hKHeap, ULONG dwSize); // Optimize for min(fragmentation_heap) - private method
static PVOID KHeapAllocateMemory(ULONG dwSize); // private method
static VOID KHeapFreeMemory(PVOID pArray); // private method
#ifdef __KHEAP_LOCK_MUTEX
static VOID KHeapLock(KHEAP hKHeap); // private method
static VOID KHeapUnLock(KHEAP hKHeap); // private method
#else
static VOID KHeapLock(KHEAP hKHeap, PKIRQL pOldIrql); // private method
static VOID KHeapUnLock(KHEAP hKHeap, KIRQL OldIrql); // private method
#endif
static BOOLEAN KHeapIsAddressValid(PVOID Address); // private method
static KHEAP hKHeapGlobalDefault = NULL;
KHEAP KHeapCreate(ULONG dwSize)
{
KHEAP hKHeap = NULL;
PMEMORY_BLOCK pBlockInfo;
if (dwSize != 0)
{
dwSize = ((dwSize+0xfff) & 0xfffff000); // Выравнивание на 4096 байт
hKHeap = (KHEAP) KHeapAllocateMemory(SIZEOF_MEMORY_BLOCK_REAL + dwSize);
if (hKHeap != NULL)
{
hKHeap->m_dwStates |= BLOCK_STATE_IN_USE | BLOCK_STATE_KHEAP;
hKHeap->m_dwSize = dwSize;
pBlockInfo = (PMEMORY_BLOCK) hKHeap->m_pArray;
pBlockInfo->m_pBaseBlock = hKHeap;
#ifdef __KHEAP_WIN32
hKHeap->m_Lock = KHeapAllocateMemory(sizeof(CRITICAL_SECTION));
if (hKHeap->m_Lock != NULL)
InitializeCriticalSection(hKHeap->m_Lock);
#else
#ifndef __KHEAP_LOCK_MUTEX
KeInitializeSpinLock(&hKHeap->m_Lock);
#else
hKHeap->m_Lock = KHeapAllocateMemory(sizeof(KMUTEX));
if (hKHeap->m_Lock != NULL)
KeInitializeMutex(hKHeap->m_Lock, 0);
else
{
KHeapFreeMemory(hKHeap);
hKHeap = NULL;
}
#endif //__KHEAP_LOCK_MUTEX
#endif //__KHEAP_WIN32
}
}
return hKHeap;
}
BOOLEAN KHeapDestroy(KHEAP hKHeap)
{
KHEAP hKHeapLast = hKHeap;
KHEAP hKHeapTmp;
if (!KHeapIsAddressValid(hKHeap) || !(hKHeap->m_dwStates & BLOCK_STATE_KHEAP))
return FALSE;
while (hKHeapLast->m_pNextBlock != NULL)
hKHeapLast = hKHeapLast->m_pNextBlock;
while (hKHeapLast->m_pBaseBlock != NULL)
{
hKHeapTmp = hKHeapLast;
hKHeapLast = hKHeapLast->m_pBaseBlock;
#ifdef __KHEAP_WIN32
if (hKHeapTmp->m_Lock != NULL)
{
DeleteCriticalSection(hKHeapTmp->m_Lock);
KHeapFreeMemory(hKHeapTmp->m_Lock);
}
#else
#ifdef __KHEAP_LOCK_MUTEX
if (hKHeapTmp->m_Lock != NULL)
KHeapFreeMemory(hKHeapTmp->m_Lock);
#endif //__KHEAP_LOCK_MUTEX
#endif
KHeapFreeMemory(hKHeapTmp);
}
#ifdef __KHEAP_WIN32
if (hKHeapLast->m_Lock != NULL)
{
DeleteCriticalSection(hKHeapLast->m_Lock);
KHeapFreeMemory(hKHeapLast->m_Lock);
}
#else
#ifdef __KHEAP_LOCK_MUTEX
if (hKHeapLast->m_Lock != NULL)
KHeapFreeMemory(hKHeapLast->m_Lock);
#endif //__KHEAP_LOCK_MUTEX
#endif
KHeapFreeMemory(hKHeapLast);
return TRUE;
}
BOOLEAN CreateDefaultHeap(ULONG dwSize)
{
if (hKHeapGlobalDefault != NULL)
DestroyDefaultHeap();
hKHeapGlobalDefault = KHeapCreate(dwSize);
return (hKHeapGlobalDefault != NULL);
}
VOID DestroyDefaultHeap(VOID)
{
KHeapDestroy(hKHeapGlobalDefault);
hKHeapGlobalDefault = NULL;
}
KHEAP KGetDefaultHeap(VOID)
{
return hKHeapGlobalDefault;
}
PVOID AllocatePoolFromKHeap(KHEAP hKHeap, ULONG dwSize)
{
ULONG dwRealSize;
PVOID pArray = NULL;
PMEMORY_BLOCK pBlockInfo, pAllocBlock = NULL, pBaseBlock;
KHEAP hKHeapNew;
PCHAR pStartFreeMem;
#ifndef __KHEAP_WIN32
#ifndef __KHEAP_LOCK_MUTEX
KIRQL OldIrqlForLock;
#endif //__KHEAP_LOCK_MUTEX
#endif //!__KHEAP_WIN32
if (hKHeap == NULL)
hKHeap = hKHeapGlobalDefault;
if (dwSize == 0 || !KHeapIsAddressValid(hKHeap))
return pArray;
dwSize = ((dwSize + 7) & 0xfffffff8);
dwRealSize = dwSize + SIZEOF_MEMORY_BLOCK_REAL;
#ifdef __KHEAP_LOCK_MUTEX
KHeapLock(hKHeap);
#else
KHeapLock(hKHeap, &OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
pBlockInfo = (PMEMORY_BLOCK)hKHeap->m_pArray;
while (pBlockInfo != NULL)
{
if (pBlockInfo->m_dwStates & BLOCK_STATE_IN_USE)
pStartFreeMem = pBlockInfo->m_pArray + pBlockInfo->m_dwSize;
else
pStartFreeMem = (char*)pBlockInfo;
if (pBlockInfo->m_pNextBlock != NULL)
{
if (
(ULONG)((char*)pBlockInfo->m_pNextBlock - pStartFreeMem) >= dwRealSize
)
{
pAllocBlock = (PMEMORY_BLOCK) pStartFreeMem;
pAllocBlock->m_pNextBlock = pBlockInfo->m_pNextBlock;
if (pStartFreeMem != (char*)pBlockInfo)
pBlockInfo->m_pNextBlock = pAllocBlock;
memset(pAllocBlock->m_pArray, 0, dwSize);
pAllocBlock->m_pBaseBlock = hKHeap;
pAllocBlock->m_dwStates = BLOCK_STATE_IN_USE;
pAllocBlock->m_dwSize = dwSize;
pArray = pAllocBlock->m_pArray;
break;
}
}
else
{
if (pBlockInfo->m_pBaseBlock != NULL)
{
pBaseBlock = pBlockInfo->m_pBaseBlock;
if (
(ULONG)((pBaseBlock->m_pArray + pBaseBlock->m_dwSize) - pStartFreeMem) >= dwRealSize
)
{
pAllocBlock = (PMEMORY_BLOCK) pStartFreeMem;
if (pStartFreeMem != (char*)pBlockInfo)
pBlockInfo->m_pNextBlock = pAllocBlock;
memset(pAllocBlock, 0, dwRealSize);
pAllocBlock->m_pBaseBlock = hKHeap;
pAllocBlock->m_dwStates |= BLOCK_STATE_IN_USE;
pAllocBlock->m_dwSize = dwSize;
pArray = pAllocBlock->m_pArray;
}
else
{
if (pBaseBlock->m_pNextBlock != NULL)
pArray = AllocatePoolFromKHeap(pBaseBlock->m_pNextBlock, dwSize);
else
{
hKHeapNew = KHeapCreate(dwRealSize > pBaseBlock->m_dwSize ? dwRealSize : pBaseBlock->m_dwSize);
if (hKHeapNew != NULL)
{
pBaseBlock->m_pNextBlock = hKHeapNew;
hKHeapNew->m_pBaseBlock = pBaseBlock;
pArray = AllocatePoolFromKHeap(pBaseBlock->m_pNextBlock, dwSize);
if (pArray == NULL)
{
KHeapDestroy(pBaseBlock->m_pNextBlock);
pBaseBlock->m_pNextBlock = NULL;
}
}
}
}
}
break;
}
pBlockInfo = pBlockInfo->m_pNextBlock;
}
#ifdef __KHEAP_LOCK_MUTEX
KHeapUnLock(hKHeap);
#else
KHeapUnLock(hKHeap, OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
return pArray;
}
PVOID _AllocatePoolFromKHeap(KHEAP hKHeap, ULONG dwSize)
{
ULONG dwRealSize;
PVOID pArray = NULL;
PMEMORY_BLOCK pAllocBlock = NULL;
KHEAP hKHeapNew;
KHEAP hKHeapAlloc;
#ifndef __KHEAP_WIN32
#ifndef __KHEAP_LOCK_MUTEX
KIRQL OldIrqlForLock;
#endif //__KHEAP_LOCK_MUTEX
#endif //!__KHEAP_WIN32
if (hKHeap == NULL)
hKHeap = hKHeapGlobalDefault;
if (dwSize == 0 || !KHeapIsAddressValid(hKHeap))
return pArray;
#ifdef __KHEAP_LOCK_MUTEX
KHeapLock(hKHeap);
#else
KHeapLock(hKHeap, &OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
pAllocBlock = KHeapGetFreeBlock(hKHeap, dwSize);
if (pAllocBlock)
{
pArray = pAllocBlock->m_pArray;
}
else
{
hKHeapAlloc = hKHeap;
while (hKHeapAlloc->m_pNextBlock)
hKHeapAlloc = hKHeapAlloc->m_pNextBlock;
dwRealSize = ((dwSize + 7) & 0xfffffff8) + SIZEOF_MEMORY_BLOCK_REAL;
hKHeapNew = KHeapCreate(dwRealSize > hKHeap->m_dwSize ? dwRealSize : hKHeap->m_dwSize);
if (hKHeapNew != NULL)
{
hKHeapAlloc->m_pNextBlock = hKHeapNew;
hKHeapNew->m_pBaseBlock = hKHeapAlloc;
pArray = _AllocatePoolFromKHeap(hKHeapAlloc->m_pNextBlock, dwSize);
if (pArray == NULL)
{
KHeapDestroy(hKHeapAlloc->m_pNextBlock);
hKHeapAlloc->m_pNextBlock = NULL;
}
}
}
#ifdef __KHEAP_LOCK_MUTEX
KHeapUnLock(hKHeap);
#else
KHeapUnLock(hKHeap, OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
return pArray;
}
VOID FreePoolToKHeap(KHEAP hKHeap, PVOID pArray)
{
PMEMORY_BLOCK pBlockInfo;
#ifndef __KHEAP_WIN32
#ifndef __KHEAP_LOCK_MUTEX
KIRQL OldIrqlForLock;
#endif //__KHEAP_LOCK_MUTEX
#endif //!__KHEAP_WIN32
if (hKHeap == NULL)
hKHeap = hKHeapGlobalDefault;
if (!KHeapIsAddressValid(hKHeap) || !KHeapIsAddressValid(pArray))
return;
#ifdef __KHEAP_LOCK_MUTEX
KHeapLock(hKHeap);
#else
KHeapLock(hKHeap, &OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
pBlockInfo = (PMEMORY_BLOCK) ((PCHAR)pArray - SIZEOF_MEMORY_BLOCK_REAL);
pBlockInfo->m_dwStates &= ~BLOCK_STATE_IN_USE;
#ifdef __KHEAP_LOCK_MUTEX
KHeapUnLock(hKHeap);
#else
KHeapUnLock(hKHeap, OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
}
PMEMORY_BLOCK KHeapGetFreeBlock(KHEAP hKHeap, ULONG dwSize)
{
PMEMORY_BLOCK pBlockInfo, pBaseBlock;
PMEMORY_BLOCK pAllocBlock = NULL, pBlockInfoSave = NULL;
ULONG dwSizeFreeBlockPrev = 0xffffffff;
KHEAP hKHeapAlloc;
ULONG dwRealSize;
PCHAR pStartFreeMem;
ULONG dwSizeFreeBlock;
dwSize = ((dwSize + 7) & 0xfffffff8);
dwRealSize = dwSize + SIZEOF_MEMORY_BLOCK_REAL;
while (hKHeap)
{
pBlockInfo = (PMEMORY_BLOCK)hKHeap->m_pArray;
while (pBlockInfo)
{
if (pBlockInfo->m_dwStates & BLOCK_STATE_IN_USE)
pStartFreeMem = pBlockInfo->m_pArray + pBlockInfo->m_dwSize;
else
pStartFreeMem = (char*)pBlockInfo;
if (pBlockInfo->m_pNextBlock != NULL)
{
dwSizeFreeBlock = (ULONG)((char*)pBlockInfo->m_pNextBlock - pStartFreeMem);
if (dwSizeFreeBlock >= dwRealSize)
{
if (dwSizeFreeBlock < dwSizeFreeBlockPrev)
{
dwSizeFreeBlockPrev = dwSizeFreeBlock;
pAllocBlock = (PMEMORY_BLOCK) pStartFreeMem;
hKHeapAlloc = hKHeap;
if (pStartFreeMem != (char*)pBlockInfo)
pBlockInfoSave = pBlockInfo;
else
pBlockInfoSave = NULL;
}
}
}
else
{
if (pBlockInfo->m_pBaseBlock != NULL)
{
pBaseBlock = pBlockInfo->m_pBaseBlock;
dwSizeFreeBlock = (ULONG)((pBaseBlock->m_pArray + pBaseBlock->m_dwSize) - pStartFreeMem);
if (dwSizeFreeBlock >= dwRealSize)
{
if (dwSizeFreeBlock < dwSizeFreeBlockPrev)
{
dwSizeFreeBlockPrev = dwSizeFreeBlock;
pAllocBlock = (PMEMORY_BLOCK) pStartFreeMem;
hKHeapAlloc = hKHeap;
if (pStartFreeMem != (char*)pBlockInfo)
pBlockInfoSave = pBlockInfo;
else
pBlockInfoSave = NULL;
}
}
}
break;
}
pBlockInfo = pBlockInfo->m_pNextBlock;
}
hKHeap = (KHEAP) hKHeap->m_pNextBlock;
}
if (pAllocBlock != NULL)
{
pAllocBlock->m_dwStates = BLOCK_STATE_IN_USE;
pAllocBlock->m_pBaseBlock = hKHeapAlloc;
pAllocBlock->m_dwSize = dwSize;
if (pBlockInfoSave != NULL) // новый блок
{
pAllocBlock->m_pNextBlock = pBlockInfoSave->m_pNextBlock;
pBlockInfoSave->m_pNextBlock = pAllocBlock;
}
// memset(pAllocBlock->m_pArray, 0, dwSize);
}
return pAllocBlock;
}
ULONG KHeapGetSizeSystemMemory(KHEAP hKHeap)
{
KHEAP hKHeapSav = hKHeap;
ULONG dwSize = 0;
#ifndef __KHEAP_WIN32
#ifndef __KHEAP_LOCK_MUTEX
KIRQL OldIrqlForLock;
#endif //__KHEAP_LOCK_MUTEX
#endif //!__KHEAP_WIN32
if (hKHeap == NULL)
hKHeap = hKHeapGlobalDefault;
if (!KHeapIsAddressValid(hKHeap))
return dwSize;
#ifdef __KHEAP_LOCK_MUTEX
KHeapLock(hKHeap);
#else
KHeapLock(hKHeap, &OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
while (hKHeapSav)
{
dwSize += hKHeapSav->m_dwSize;
hKHeapSav = (KHEAP) hKHeapSav->m_pNextBlock;
}
#ifdef __KHEAP_LOCK_MUTEX
KHeapUnLock(hKHeap);
#else
KHeapUnLock(hKHeap, OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
return dwSize;
}
ULONG KHeapGetSizeUsageMemory(KHEAP hKHeap)
{
PMEMORY_BLOCK pBlockInfo;
ULONG dwSize = 0;
KHEAP hKHeapSav = hKHeap;
#ifndef __KHEAP_WIN32
#ifndef __KHEAP_LOCK_MUTEX
KIRQL OldIrqlForLock;
#endif //__KHEAP_LOCK_MUTEX
#endif //!__KHEAP_WIN32
if (hKHeap == NULL)
hKHeap = hKHeapGlobalDefault;
if (!KHeapIsAddressValid(hKHeap))
return dwSize;
#ifdef __KHEAP_LOCK_MUTEX
KHeapLock(hKHeap);
#else
KHeapLock(hKHeap, &OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
while (hKHeapSav)
{
pBlockInfo = (PMEMORY_BLOCK)hKHeapSav->m_pArray;
while (pBlockInfo)
{
if (pBlockInfo->m_dwStates & BLOCK_STATE_IN_USE)
dwSize += pBlockInfo->m_dwSize;
pBlockInfo = pBlockInfo->m_pNextBlock;
}
hKHeapSav = (KHEAP) hKHeapSav->m_pNextBlock;
}
#ifdef __KHEAP_LOCK_MUTEX
KHeapUnLock(hKHeap);
#else
KHeapUnLock(hKHeap, OldIrqlForLock);
#endif //__KHEAP_LOCK_MUTEX
return dwSize;
}
PVOID KHeapAllocateMemory(ULONG dwSize)
{
PVOID pArray = NULL;
if (dwSize)
{
#ifdef __KHEAP_WIN32
pArray = malloc(dwSize);
#else
pArray = ExAllocatePool(NonPagedPool, dwSize);
#endif
if (pArray != NULL)
memset(pArray, 0, dwSize);
}
return pArray;
}
VOID KHeapFreeMemory(PVOID pArray)
{
if (KHeapIsAddressValid(pArray))
{
#ifdef __KHEAP_WIN32
free(pArray);
#else
ExFreePool(pArray);
#endif
}
}
#ifdef __KHEAP_LOCK_MUTEX
VOID KHeapLock(KHEAP hKHeap)
#else
VOID KHeapLock(KHEAP hKHeap, PKIRQL pOldIrql)
#endif //__KHEAP_LOCK_MUTEX
{
if (KHeapIsAddressValid(hKHeap))
{
#ifdef __KHEAP_WIN32
if (hKHeap->m_Lock != NULL)
EnterCriticalSection(hKHeap->m_Lock);
#else
#ifndef __KHEAP_LOCK_MUTEX
KeAcquireSpinLock(&hKHeap->m_Lock, pOldIrql);//(KIRQL*)&hKHeap->m_OldIrql);
#else
KeWaitForMutexObject(hKHeap->m_Lock, Executive, KernelMode, FALSE, NULL);
#endif //__KHEAP_LOCK_MUTEX
#endif
}
}
#ifdef __KHEAP_LOCK_MUTEX
VOID KHeapUnLock(KHEAP hKHeap)
#else
VOID KHeapUnLock(KHEAP hKHeap, KIRQL OldIrql)
#endif //__KHEAP_LOCK_MUTEX
{
if (KHeapIsAddressValid(hKHeap))
{
#ifdef __KHEAP_WIN32
if (hKHeap->m_Lock != NULL)
LeaveCriticalSection(hKHeap->m_Lock);
#else
#ifndef __KHEAP_LOCK_MUTEX
KeReleaseSpinLock(&hKHeap->m_Lock, OldIrql);//(KIRQL)hKHeap->m_OldIrql);
#else
KeReleaseMutex(hKHeap->m_Lock, FALSE);
#endif //__KHEAP_LOCK_MUTEX
#endif
}
}
BOOLEAN KHeapIsAddressValid(PVOID Address)
{
if (!Address)
return FALSE;
return MmIsAddressValid(Address);
}