windows-nt/Source/XPSP1/NT/inetsrv/iis/setup/util/migrate/poolmem.cpp
2020-09-26 16:20:57 +08:00

201 lines
4.6 KiB
C++

#include "stdafx.h"
// Tree Memory Allocation structure.
typedef struct _POOLMEMORYBLOCK POOLMEMORYBLOCK, *PPOOLMEMORYBLOCK;
struct _POOLMEMORYBLOCK {
DWORD_PTR Index;
DWORD_PTR Size;
PPOOLMEMORYBLOCK NextBlock;
PPOOLMEMORYBLOCK PrevBlock;
PBYTE RawMemory;
};
typedef struct _POOLHEADER {
PPOOLMEMORYBLOCK PoolHead;
HANDLE Heap;
} POOLHEADER, *PPOOLHEADER;
BOOL
PoolMemAddMemory (
IN POOLHANDLE Handle,
IN DWORD_PTR Size
)
{
PBYTE allocedMemory;
PPOOLMEMORYBLOCK newBlock;
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
DWORD_PTR 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 = (unsigned char *) 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 = (PPOOLHEADER) 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_PTR Size,
IN DWORD_PTR AlignSize
)
{
BOOL haveEnoughMemory = TRUE;
PVOID rMemory = NULL;
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
PPOOLMEMORYBLOCK currentBlock;
DWORD_PTR sizeNeeded;
DWORD_PTR 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_PTR) 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;
}