#include "poolmem.h" // Tree Memory Allocation structure. typedef struct _POOLMEMORYBLOCK POOLMEMORYBLOCK, *PPOOLMEMORYBLOCK; struct _POOLMEMORYBLOCK { DWORD Index; DWORD Size; PPOOLMEMORYBLOCK NextBlock; PPOOLMEMORYBLOCK PrevBlock; PBYTE RawMemory; }; typedef struct _POOLHEADER { PPOOLMEMORYBLOCK PoolHead; HANDLE Heap; } POOLHEADER, *PPOOLHEADER; BOOL PoolMemAddMemory ( IN POOLHANDLE Handle, IN DWORD Size ) { PBYTE allocedMemory; PPOOLMEMORYBLOCK newBlock; PPOOLHEADER poolHeader = (PPOOLHEADER) Handle; DWORD sizeNeeded; assert(poolHeader != NULL); // // Determine size needed and attempt to allocate memory. // if (Size + sizeof(POOLMEMORYBLOCK) > POOLMEMORYBLOCKSIZE) { sizeNeeded = Size + sizeof(POOLMEMORYBLOCK); } else { sizeNeeded = POOLMEMORYBLOCKSIZE; } allocedMemory = HeapAlloc(poolHeader -> Heap,0,sizeNeeded); if (allocedMemory) { // // Use the beginning of the alloc'ed block as the poolblock structure. // newBlock = (PPOOLMEMORYBLOCK) allocedMemory; newBlock -> Size = sizeNeeded - sizeof(POOLMEMORYBLOCK); newBlock -> RawMemory = allocedMemory + sizeof(POOLMEMORYBLOCK); newBlock -> Index = 0; // // Link the block into the list. // if (poolHeader -> PoolHead) { poolHeader -> PoolHead -> PrevBlock = newBlock; } newBlock -> NextBlock = poolHeader -> PoolHead; newBlock -> PrevBlock = NULL; poolHeader -> PoolHead = newBlock; } // // Assuming allocedMemory is non-NULL, we have succeeded. // return allocedMemory != NULL; } POOLHANDLE WINAPI PoolMemInitPool ( ) { BOOL ableToAddMemory; PPOOLHEADER header = NULL; HANDLE procHeap; procHeap = GetProcessHeap(); // // Allocate the header of this pool. // header = HeapAlloc(procHeap,0,sizeof(POOLHEADER)); if (header) { // // Allocation was successful. Now, initialize the pool. // header -> PoolHead = NULL; header -> Heap = procHeap; // // Actually add some memory to the pool. // ableToAddMemory = PoolMemAddMemory(header,0); if (!ableToAddMemory) { // // Unable to add memory to the pool. // HeapFree(header -> Heap,0,header); header = NULL; } } return (POOLHANDLE) header; } VOID WINAPI PoolMemDestroyPool ( POOLHANDLE Handle ) { PPOOLMEMORYBLOCK nextBlock; PPOOLMEMORYBLOCK blockToFree; PPOOLHEADER poolHeader; assert(Handle != NULL); poolHeader = (PPOOLHEADER) Handle; // // Walk the list, freeing as we go. // blockToFree = poolHeader -> PoolHead; while (blockToFree != NULL) { nextBlock = blockToFree->NextBlock; HeapFree(poolHeader -> Heap,0,blockToFree); blockToFree = nextBlock; } // // Also, deallocate the poolheader itself. // HeapFree(poolHeader -> Heap,0,poolHeader); } PVOID WINAPI PoolMemGetAlignedMemory ( IN POOLHANDLE Handle, IN DWORD Size, IN DWORD AlignSize ) { BOOL haveEnoughMemory = TRUE; PVOID rMemory = NULL; PPOOLHEADER poolHeader = (PPOOLHEADER) Handle; PPOOLMEMORYBLOCK currentBlock; DWORD sizeNeeded; DWORD padLength; assert(poolHeader != NULL); currentBlock = poolHeader -> PoolHead; // Determine if more memory is needed, attempt to add if needed. sizeNeeded = Size; if (currentBlock -> Size - currentBlock -> Index < sizeNeeded + AlignSize) { haveEnoughMemory = PoolMemAddMemory(poolHeader,sizeNeeded + AlignSize); currentBlock = poolHeader -> PoolHead; } // If there is enough memory available, return it. if (haveEnoughMemory) { if (AlignSize) { padLength = (DWORD) currentBlock + sizeof(POOLMEMORYBLOCK) + currentBlock -> Index; currentBlock -> Index += (AlignSize - (padLength % AlignSize)) % AlignSize; } //Now, get the address of the memory to return. rMemory = (PVOID) &(currentBlock->RawMemory[currentBlock -> Index]); currentBlock->Index += sizeNeeded; } return rMemory; }