Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1619 lines
34 KiB

//--------------------------------------------------------------------------;
//
// File: Exact.c
//
// Copyright (C) Microsoft Corporation, 1993 - 1996 All rights reserved
//
// Abstract:
// Contains exact memory allocation routines.
//
// Contents:
// GetPageSize()
// SetExactHeaderInfo()
// GetExactHeaderInfo()
// ExactAllocPtr()
// ExactFreePtr()
// GetNumAllocations()
// GetMemoryHandle()
// ExactSize()
// ExactReAllocPtr()
// GetPointer()
// SetPointer()
// ExactHeapAllocPtr()
// ExactHeapCreate()
// ExactHeapDestroy()
// ExactHeapFreePtr()
// ExactHeapReAllocPtr()
// ExactHeapSize()
//
// History:
// 12/01/93 Fwong Verifying correctness.
// 01/14/94 Fwong Adding Win32 Support.
//
//--------------------------------------------------------------------------;
#include <windows.h>
#ifdef WIN32
#include <windowsx.h>
#endif
//==========================================================================;
//
// Structures...
//
//==========================================================================;
#ifdef WIN32
typedef struct EXACTHDR_tag
{
DWORD fdwFlags;
LPVOID pEvil;
LPVOID pStart;
} EXACTHDR;
typedef EXACTHDR *PEXACTHDR;
typedef EXACTHDR NEAR *NPEXACTHDR;
typedef EXACTHDR FAR *LPEXACTHDR;
#else
typedef struct EXACTHDR_tag
{
DWORD fdwFlags;
HGLOBAL hMem;
} EXACTHDR;
typedef EXACTHDR *PEXACTHDR;
typedef EXACTHDR NEAR *NPEXACTHDR;
typedef EXACTHDR FAR *LPEXACTHDR;
#endif
typedef struct EXACTHEAP_tag
{
HGLOBAL hMem;
DWORD cNumAlloc;
DWORD cMaxAlloc;
DWORD fdwFlags;
LPVOID pPointers;
} EXACTHEAP;
typedef EXACTHEAP *PEXACTHEAP;
typedef EXACTHEAP NEAR *NPEXACTHEAP;
typedef EXACTHEAP FAR *LPEXACTHEAP;
//==========================================================================;
//
// Constants...
//
//==========================================================================;
#define EXACTMEM_SIGNATURE 0xdead0000
#define EXACTMEM_SIGNATUREMASK 0xffff0000
#define EXACTMEM_HANDLE 0x00000001
#define EXACTMEM_INUSE 0x00000002
#define HEAPCHUNKSIZE 32
//==========================================================================;
//
// Macros...
//
//==========================================================================;
#define IS_BAD_HEADER_SIGNATURE(a) (EXACTMEM_SIGNATURE != \
((a).fdwFlags & EXACTMEM_SIGNATUREMASK))
#define IS_BAD_HEAP_SIGNATURE(a) (EXACTMEM_SIGNATURE != \
((a)->fdwFlags & EXACTMEM_SIGNATUREMASK))
#define LOCK_HEAP(a) ((a)->fdwFlags |= EXACTMEM_INUSE)
#define UNLOCK_HEAP(a) ((a)->fdwFlags &= (~EXACTMEM_INUSE))
#ifdef WIN32
#define WAIT_FOR_HEAP(a) while((a)->fdwFlags & EXACTMEM_INUSE) Sleep(0)
#else
#define WAIT_FOR_HEAP(a) while((a)->fdwFlags & EXACTMEM_INUSE)
#endif
//==========================================================================;
//
// Debug Stuff...
//
//==========================================================================;
#ifdef DEBUG
#define DBGOUT(a) OutputDebugString("MEMGR:" a "\r\n");
#else
#define DBGOUT(a) //
#endif
#define DIVRU(a,b) (((a)/(b)) + (((a)%(b))?1:0))
DWORD gcAllocations = 0L;
//--------------------------------------------------------------------------;
//
// DWORD GetPageSize
//
// Description:
// Gets the page size for this platform.
//
// Arguments:
// None.
//
// Return (DWORD):
// Size (in bytes) of a page.
//
// History:
// 08/09/94 Fwong Retroactive commenting. <Internal>
//
//--------------------------------------------------------------------------;
#ifdef WIN32
DWORD GetPageSize
(
void
)
{
SYSTEM_INFO sinf;
GetSystemInfo(&sinf);
return (sinf.dwPageSize);
} // GetPageSize()
#endif // WIN32
//--------------------------------------------------------------------------;
//
// BOOL SetExactHeaderInfo
//
// Description:
// Given a pointer to an ExactAlloc'ed buffer, it stores the header
// information.
//
// Arguments:
// LPVOID pStart: Pointer to ExactAlloc'ed buffer.
//
// LPEXACTHDR pExactHdr: Pointer to header.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 08/10/94 Fwong Facilitating writing headers. <Internal>
//
//--------------------------------------------------------------------------;
BOOL SetExactHeaderInfo
(
LPVOID pStart,
LPEXACTHDR pExactHdr
)
{
pStart = ((LPBYTE)pStart) - sizeof(EXACTHDR);
if(IsBadWritePtr(pStart,sizeof(EXACTHDR)))
{
return FALSE;
}
hmemcpy(pStart,pExactHdr,sizeof(EXACTHDR));
return TRUE;
} // SetExactHeaderInfo()
//--------------------------------------------------------------------------;
//
// BOOL GetExactHeaderInfo
//
// Description:
// Given a pointer to an ExactAlloc'ed buffer, it stores the header
// information.
//
// Arguments:
// LPVOID pStart: Pointer to ExactAlloc'ed buffer.
//
// LPEXACTHDR pExactHdr: Pointer to header.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 08/10/94 Fwong Facilitating reading headers. <Internal>
//
//--------------------------------------------------------------------------;
BOOL GetExactHeaderInfo
(
LPVOID pStart,
LPEXACTHDR pExactHdr
)
{
pStart = ((LPBYTE)pStart) - sizeof(EXACTHDR);
if(IsBadReadPtr(pStart,sizeof(EXACTHDR)))
{
return FALSE;
}
hmemcpy(pExactHdr,pStart,sizeof(EXACTHDR));
return TRUE;
} // GetExactHeaderInfo()
//==========================================================================;
//
// Explanation: Okay, before I get flamed. This is the explanation of
// how things work in the Win32 version of ExactAllocPtr(); it is
// relatively non-trivial.
//
// Windows NT sets memory access on a per page basis. You can mark a page
// of memory with certain access rights. The concept is to return a
// pointer that will hit a PAGE_NOACCESS page on the boundary.
// Like this...
//
// ----|-----------|-----------|-no-access-|-----------|-----------|-----
// ^
// +---- pointer n bytes from "no access" page
//
// Very simple. However, you shouldn't be marking a page as PAGE_NOACCESS
// unless you own the entire page. (Windows NT doesn't hesitate
// allocating memory within the same page with GlobalAlloc, and having
// other things faulting).
//
// The only way to guarantee getting a full block is to allocate at a
// buffer at least a full block larger in length. So we have
// something that looks like this...
//
// |<----buffer-length---->|
// ----|-----------|-----------|-no-access-|-----------|-----------|-----
// ^ ^
// +------+---- actual pointer from allocation
// +---- offset pointer to return
//
// Note: Since the implementation changed to using VirtualAlloc (formerly
// used GlobalAlloc), we are guaranteed all memory allocations to be
// on page boundaries.
//
// In addition, we also need to keep track of some other things (so that
// we can free the memory and return the access rights on the "no
// access" page to "read/write access". Moreover, to confirm that
// the memory allocation was actually done by us, we also put in a
// "signature." These are all stored in a header, which is stored
// right before the pointer to return. It should look like this...
//
// |<----buffer-length---->|
// ----|-----------|-----------|-no-access-|-----------|-----------|-----
// ^ ^ ^
// +----+-+---- actual pointer from allocation
// + +---- offset pointer to return
// +------ location to store header information
//
// Note: Due to alignment problems (with the MIPS architecture) with
// writing the header data directly into memory, we're doing an
// hmemcpy to from a local header. It may look bad and/or
// ugly. DON'T CHANGE IT! IT WORKS!
//
//==========================================================================;
//--------------------------------------------------------------------------;
//
// LPVOID ExactAllocPtr
//
// Description:
// Performs an exact memory allocation.
//
// Note: WIN32 Version counts on VirtualAlloc allocating memory in
// page boundaries.
//
// Arguments:
// UINT fuAlloc: Flags for GlobalAlloc. These are ignored for WIN32.
//
// DWORD cbAlloc: Size of Buffer.
//
// Return (LPVOID):
// Pointer to allocated buffer.
//
// History:
// 11/17/93 Fwong Created for exact allocation management.
// 01/14/94 Fwong Adding Win32 Support.
// 01/26/94 Fwong Revising to workaround NT problem.
// 08/02/94 Fwong Changing to use VirtualAlloc.
//
//--------------------------------------------------------------------------;
#ifdef WIN32
LPVOID ExactAllocPtr
(
UINT fuAlloc,
DWORD cbAlloc
)
{
static DWORD dwPageSize = 0L;
DWORD dw;
DWORD cbActual;
DWORD cbExtra;
EXACTHDR ExactHdr;
LPVOID pCurrent;
if(0 == dwPageSize)
{
dwPageSize = GetPageSize();
}
//
// Header info...
//
cbExtra = sizeof(EXACTHDR);
//
// dw = Number of Pages to allocate.
// cbActual = Number of bytes.
//
dw = DIVRU(cbAlloc + cbExtra, dwPageSize) + 1;
cbActual = dw * dwPageSize;
//
// Getting pointer...
//
ExactHdr.pStart = VirtualAlloc(
NULL,
cbActual,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
if(NULL == ExactHdr.pStart)
{
//
// Something failed here...
//
DBGOUT("VirtualAlloc failed.");
return NULL;
}
//
// pEvil = first byte in last page.
//
ExactHdr.pEvil = ((LPBYTE)ExactHdr.pStart) + cbActual - dwPageSize;
//
// pCurrent = cbAlloc number of bytes from "Evil" page.
//
pCurrent = ((LPBYTE)ExactHdr.pEvil) - cbAlloc;
//
// Making page "Evil"!
//
if(FALSE == VirtualProtect(ExactHdr.pEvil,1,PAGE_NOACCESS,&dw))
{
//
// VirtualProtect failed. Failing ExactAllocPtr.
//
DBGOUT("VirtualProtect failed.");
VirtualFree(ExactHdr.pStart,0,MEM_RELEASE);
return NULL;
}
ExactHdr.fdwFlags = EXACTMEM_SIGNATURE;
//
// Storing header information.
//
SetExactHeaderInfo(pCurrent,&ExactHdr);
gcAllocations++;
return (LPVOID)(((LPBYTE)ExactHdr.pEvil) - cbAlloc);
} // ExactAllocPtr()
#else
LPVOID ExactAllocPtr
(
UINT fuAlloc,
DWORD cbAlloc
)
{
HGLOBAL hMem;
EXACTHDR ExactHdr;
LPBYTE pbyte;
hMem = GlobalAlloc(fuAlloc,cbAlloc + sizeof(EXACTHDR));
//
// Something failed here...
//
if(NULL == hMem)
{
DBGOUT("GlobalAlloc failed.");
return NULL;
}
//
// Offsetting the pointer by the amount of "extra" bytes.
// extra bytes = actual (GlobalSize) - wanted (cbAlloc)
//
pbyte = (LPBYTE)GlobalLock(hMem);
if(NULL == pbyte)
{
DBGOUT("GlobalLock failed.");
GlobalFree(hMem);
return NULL;
}
pbyte += (GlobalSize(hMem) - cbAlloc);
ExactHdr.hMem = hMem;
ExactHdr.fdwFlags = EXACTMEM_SIGNATURE;
//
// Storing Header information.
//
SetExactHeaderInfo(pbyte,&ExactHdr);
gcAllocations++;
return pbyte;
} // ExactAllocPtr()
#endif
//--------------------------------------------------------------------------;
//
// BOOL ExactFreePtr
//
// Description:
// Frees a previously allocated pointer.
//
// Arguments:
// LPVOID pvoid: Pointer to buffer.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 11/17/93 Fwong Created for exact allocation management.
// 01/26/94 Fwong Adding stuff to workaround NT problem.
// 08/08/94 Fwong Changed to use VirtualFree.
//
//--------------------------------------------------------------------------;
BOOL ExactFreePtr
(
LPVOID pvoid
)
{
EXACTHDR ExactHdr;
if(NULL == pvoid)
{
DBGOUT("Bad Pointer.");
return FALSE;
}
//
// Retrieving header info.
//
if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
{
DBGOUT("Bad Header.");
return FALSE;
}
//
// Is the signature correct?
//
if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
{
DBGOUT("Bad Signature.");
return FALSE;
}
//
// Was it allocated through "Handle" API's?
//
if(EXACTMEM_HANDLE & ExactHdr.fdwFlags)
{
DBGOUT("Using Heap memory for non heap API.");
return FALSE;
}
#ifdef WIN32
{
DWORD dw;
//
// Setting access rights back to PAGE_READWRITE.
//
if(FALSE == VirtualProtect(ExactHdr.pEvil,1,PAGE_READWRITE,&dw))
{
//
// What is wrong now?!
//
DBGOUT("VirtualProtect failed.");
return FALSE;
}
//
// Freeing memory.
//
if(FALSE == VirtualFree(ExactHdr.pStart,0,MEM_RELEASE))
{
//
// VirtualFree failed?!
//
DBGOUT("VirtualFree failed.");
return FALSE;
}
}
#else
GlobalUnlock(ExactHdr.hMem);
if(NULL != GlobalFree(ExactHdr.hMem))
{
DBGOUT("GlobalFree failed.");
return FALSE;
}
#endif
gcAllocations--;
return TRUE;
} // ExactFreePtr()
//--------------------------------------------------------------------------;
//
// DWORD GetNumAllocations
//
// Description:
// Returns the number of allocations that have been performed through
// memgr.
//
// Arguments:
// None.
//
// Return (DWORD):
// Count of number of allocations.
//
// History:
// 06/06/94 Fwong To minimize memory leaks.
//
//--------------------------------------------------------------------------;
DWORD GetNumAllocations
(
void
)
{
return gcAllocations;
} // GetNumAllocations()
//--------------------------------------------------------------------------;
//
// HGLOBAL GetMemoryHandle
//
// Description:
// Given a pointer (allocated by memgr) it returns the handle.
//
// Arguments:
// LPVOID pvoid: Pointer to buffer.
//
// Return (HGLOBAL):
// handle to memory.
//
// History:
// 06/06/94 Fwong To make things more flexible.
//
//--------------------------------------------------------------------------;
#ifdef WIN32
HGLOBAL GetMemoryHandle
(
LPVOID pvoid
)
{
//
// The algorithm does not use memory handles for WIN32 anymore.
//
return NULL;
} // GetMemoryHandle()
#else
HGLOBAL GetMemoryHandle
(
LPVOID pvoid
)
{
EXACTHDR ExactHdr;
if(NULL == pvoid)
{
DBGOUT("Bad Pointer.");
return NULL;
}
//
// Retrieving header info.
//
if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
{
DBGOUT("Bad Header.");
return NULL;
}
//
// Is the signature correct?
//
if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
{
DBGOUT("Bad Signature.");
return NULL;
}
return (HGLOBAL)(ExactHdr.hMem);
} // GetMemoryHandle()
#endif
//--------------------------------------------------------------------------;
//
// DWORD ExactSize
//
// Description:
// Given an ExactAlloc'ed pointer, it returns the "exact" size of the
// buffer.
//
// Arguments:
// LPVOID pvoid: Originally ExactAlloc'ed pointer.
//
// Return (DWORD):
// Size (in bytes) of buffer; Zero if an error occurs.
//
// History:
// 08/08/94 Fwong Adding this for ReAlloc support.
//
//--------------------------------------------------------------------------;
#ifdef WIN32
DWORD ExactSize
(
LPVOID pvoid
)
{
EXACTHDR ExactHdr;
if(NULL == pvoid)
{
DBGOUT("Bad Pointer.");
return 0L;
}
//
// Retrieving header info.
//
if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
{
DBGOUT("Bad Header.");
return 0L;
}
//
// Is the signature correct?
//
if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
{
DBGOUT("Bad Signature.");
return 0L;
}
return (DWORD)(((LPBYTE)ExactHdr.pEvil) - (LPBYTE)(pvoid));
} // ExactSize()
#else
DWORD ExactSize
(
LPVOID pvoid
)
{
EXACTHDR ExactHdr;
DWORD dw;
if(NULL == pvoid)
{
DBGOUT("Bad Pointer.");
return 0L;
}
//
// Retrieving header info.
//
if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
{
DBGOUT("Bad Header.");
return 0L;
}
//
// Is the signature correct?
//
if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
{
DBGOUT("Bad Signature.");
return 0L;
}
dw = LOWORD(pvoid);
return (DWORD)(GlobalSize(ExactHdr.hMem) - dw);
} // ExactSize()
#endif
//--------------------------------------------------------------------------;
//
// LPVOID ExactReAlloc
//
// Description:
// Re-allocates the buffer to be a different size of different
// allocation flags.
//
// Note: Don't count on the pointer remaining the same; the pointer
// _WILL_ change.
//
// Arguments:
// LPVOID pOldPtr: Pointer to old buffer.
//
// DWORD cbAlloc: Number of bytes to re-allocate to.
//
// UINT fuAlloc: Allocation flags.
//
// Return (LPVOID):
// Pointer to buffer, or NULL if unsuccessful.
//
// History:
// 08/08/94 Fwong To make life a little easier.
//
//--------------------------------------------------------------------------;
LPVOID ExactReAllocPtr
(
LPVOID pOldPtr,
DWORD cbAlloc,
UINT fuAlloc
)
{
LPVOID pNewPtr;
DWORD dw;
EXACTHDR ExactHdr;
//
// Retrieving header info.
//
if(FALSE == GetExactHeaderInfo(pOldPtr,&ExactHdr))
{
DBGOUT("Bad Header.");
return NULL;
}
//
// Is the signature correct?
//
if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
{
DBGOUT("Bad Signature.");
return NULL;
}
//
// Was it allocated through "Handle" API's?
//
if(EXACTMEM_HANDLE & ExactHdr.fdwFlags)
{
DBGOUT("Using heap memory for non heap API.");
return NULL;
}
pNewPtr = ExactAllocPtr(fuAlloc,cbAlloc);
if(NULL == pNewPtr)
{
DBGOUT("ExactAllocPtr failed.");
return NULL;
}
//
// Determining how many bytes to copy over...
//
dw = ExactSize(pOldPtr);
dw = min(dw,cbAlloc);
hmemcpy(pNewPtr,pOldPtr,dw);
ExactFreePtr(pOldPtr);
return pNewPtr;
} // ExactReAllocPtr()
//--------------------------------------------------------------------------;
//
// LPVOID GetPointer
//
// Description:
// Given the index, gets the pointer from a buffer of pointers.
//
// Note: This was done very carefully due to the alignment problems
// with MIPS machines. DON'T MESS WITH IT!
//
// Arguments:
// LPVOID pvoid: Pointer to buffer.
//
// DWORD index: Index into buffer.
//
// Return (LPVOID):
// The pointer at the appropriate index.
//
// History:
// 08/11/94 Fwong For Heap Management. <Internal>
//
//--------------------------------------------------------------------------;
LPVOID GetPointer
(
LPVOID pvoid,
DWORD index
)
{
LPVOID pReturn;
index *= sizeof(LPVOID);
pvoid = ((LPBYTE)pvoid) + index;
hmemcpy((LPVOID)(&pReturn),pvoid,sizeof(LPVOID));
return pReturn;
} // GetPointer()
//--------------------------------------------------------------------------;
//
// void SetPointer
//
// Description:
// Given the index, sets a pointer within a buffer of pointers.
//
// Note: This was done very carefully due to the alignment problems
// with MIPS machines. DON'T MESS WITH IT!
//
// Arguments:
// LPVOID pvoid: Pointer to buffer.
//
// DWORD index: Index into buffer.
//
// LPVOID ptr: Pointer to store.
//
// Return (void):
//
// History:
// 08/11/94 Fwong For Heap Management. <Internal>
//
//--------------------------------------------------------------------------;
void SetPointer
(
LPVOID pvoid,
DWORD index,
LPVOID ptr
)
{
index *= sizeof(LPVOID);
pvoid = ((LPBYTE)pvoid) + index;
hmemcpy(pvoid,(LPVOID)(&ptr),sizeof(LPVOID));
} // SetPointer()
//--------------------------------------------------------------------------;
//
// LPVOID ExactHeapAllocPtr
//
// Description:
// ExactAlloc's a buffer through a heap handle.
//
// Arguments:
// HANDLE hHeap: Handle to heap.
//
// UINT fuAlloc: Allocation flags for memory (See GlobalAlloc).
//
// DWORD cbAlloc: Size (in bytes) of buffer.
//
// Return (LPVOID):
// Pointer to buffer, or NULL if an error occurs.
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
LPVOID ExactHeapAllocPtr
(
HANDLE hHeap,
UINT fuAlloc,
DWORD cbAlloc
)
{
NPEXACTHEAP npExactHeap;
EXACTHDR ExactHdr;
LPVOID pNewMem;
HGLOBAL hMem;
DWORD dw;
npExactHeap = (NPEXACTHEAP)hHeap;
//
// Checking if it is a bad pointer.
//
if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
{
DBGOUT("Bad hHeap.");
return NULL;
}
//
// Checking if it is a bad handle.
//
if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
{
DBGOUT("Bad hHeap.");
return NULL;
}
//
// If someone else has a hold of the heap, we wait.
//
WAIT_FOR_HEAP(npExactHeap);
LOCK_HEAP(npExactHeap);
//
// Can we store the pointer?
//
if(npExactHeap->cNumAlloc == npExactHeap->cMaxAlloc)
{
//
// Getting room for HEAPCHUNKSIZE number of more items
//
dw = (npExactHeap->cMaxAlloc + HEAPCHUNKSIZE) * sizeof(LPVOID);
hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,dw);
if(NULL == hMem)
{
DBGOUT("GlobalAlloc failed.");
UNLOCK_HEAP(npExactHeap);
return NULL;
}
pNewMem = GlobalLock(hMem);
if(NULL == pNewMem)
{
DBGOUT("GlobalLock failed.");
GlobalFree(hMem);
UNLOCK_HEAP(npExactHeap);
return NULL;
}
//
// Copying all old pointers.
//
dw = npExactHeap->cMaxAlloc * sizeof(LPVOID);
hmemcpy(pNewMem,npExactHeap->pPointers,dw);
//
// Freeing old buffer.
//
GlobalUnlock(npExactHeap->hMem);
GlobalFree(npExactHeap->hMem);
//
// Updating heap header.
//
npExactHeap->cMaxAlloc += HEAPCHUNKSIZE;
npExactHeap->hMem = hMem;
npExactHeap->pPointers = pNewMem;
}
pNewMem = ExactAllocPtr(fuAlloc,cbAlloc);
if(NULL == pNewMem)
{
DBGOUT("ExactAllocPtr failed.");
UNLOCK_HEAP(npExactHeap);
return NULL;
}
//
// Marking buffer as allocated by HEAP API's.
//
GetExactHeaderInfo(pNewMem,&ExactHdr);
ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
SetExactHeaderInfo(pNewMem,&ExactHdr);
//
// Updating Heap info.
//
SetPointer(npExactHeap->pPointers,npExactHeap->cNumAlloc,pNewMem);
npExactHeap->cNumAlloc++;
UNLOCK_HEAP(npExactHeap);
return pNewMem;
} // ExactHeapAllocPtr()
//--------------------------------------------------------------------------;
//
// HANDLE ExactHeapCreate
//
// Description:
// Creates a heap to do subsequent memory allocations.
//
// Arguments:
// DWORD fdwFlags: Flags for function (none are defined yet).
//
// Return (HANDLE):
// Handle to heap, or NULL if an error occured.
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
HANDLE ExactHeapCreate
(
DWORD fdwFlags
)
{
NPEXACTHEAP npExactHeap;
HGLOBAL hMem;
npExactHeap = (NPEXACTHEAP)LocalAlloc(LPTR,sizeof(EXACTHEAP));
if(NULL == npExactHeap)
{
DBGOUT("LocalAlloc failed.");
return NULL;
}
hMem = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,HEAPCHUNKSIZE*sizeof(LPVOID));
if(NULL == hMem)
{
DBGOUT("GlobalAlloc failed.");
LocalFree((HLOCAL)npExactHeap);
return NULL;
}
npExactHeap->pPointers = GlobalLock(hMem);
if(NULL == npExactHeap->pPointers)
{
DBGOUT("GlobalLock failed.");
GlobalFree(hMem);
LocalFree((HLOCAL)npExactHeap);
return NULL;
}
npExactHeap->fdwFlags = EXACTMEM_SIGNATURE;
npExactHeap->cNumAlloc = 0L;
npExactHeap->cMaxAlloc = HEAPCHUNKSIZE;
npExactHeap->hMem = hMem;
return (HANDLE)(npExactHeap);
} // ExactHeapCreate()
//--------------------------------------------------------------------------;
//
// BOOL ExactHeapDestroy
//
// Description:
// "Destroys" heap. Invalidates handle and frees all associated
// memory allocations.
//
// Arguments:
// HANDLE hHeap: Handle to heap.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
BOOL ExactHeapDestroy
(
HANDLE hHeap
)
{
NPEXACTHEAP npExactHeap;
EXACTHDR ExactHdr;
LPVOID pMem;
DWORD dw;
npExactHeap = (NPEXACTHEAP)hHeap;
//
// Checking if it is a bad pointer.
//
if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
{
DBGOUT("Bad hHeap.");
return FALSE;
}
//
// Checking if it is a bad handle.
//
if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
{
DBGOUT("Bad hHeap.");
return FALSE;
}
//
// If someone else has a hold of the heap, we wait.
//
WAIT_FOR_HEAP(npExactHeap);
LOCK_HEAP(npExactHeap);
//
// Freeing all memory...
//
for(dw = npExactHeap->cNumAlloc;dw;dw--)
{
pMem = GetPointer(npExactHeap->pPointers,dw-1);
GetExactHeaderInfo(pMem,&ExactHdr);
ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
SetExactHeaderInfo(pMem,&ExactHdr);
if(FALSE == ExactFreePtr(pMem))
{
DBGOUT("ExactFreePtr failed.");
UNLOCK_HEAP(npExactHeap);
return FALSE;
}
}
//
// Invalidating handle... Just in case.
//
npExactHeap->fdwFlags = 0L;
//
// Freeing memory.
//
GlobalUnlock(npExactHeap->hMem);
GlobalFree(npExactHeap->hMem);
LocalFree((HLOCAL)(npExactHeap));
return TRUE;
} // ExactHeapDestroy()
//--------------------------------------------------------------------------;
//
// BOOL ExactHeapFreePtr
//
// Description:
// Frees memory allocated through ExactHeapAllocPtr.
//
// Arguments:
// HANDLE hHeap: Handle to heap.
//
// UINT fuFree: Flags for function (None are defined yet).
//
// LPVOID pMemFree: Buffer to free.
//
// Return (BOOL):
// TRUE if successful, FALSE otherwise.
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
BOOL ExactHeapFreePtr
(
HANDLE hHeap,
UINT fuFree,
LPVOID pMemFree
)
{
NPEXACTHEAP npExactHeap;
EXACTHDR ExactHdr;
LPVOID pMem;
DWORD dw;
npExactHeap = (NPEXACTHEAP)hHeap;
//
// Checking if it is a bad pointer.
//
if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
{
DBGOUT("Bad hHeap.");
return FALSE;
}
//
// Checking if it is a bad handle.
//
if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
{
DBGOUT("Bad hHeap.");
return FALSE;
}
//
// If someone else has a hold of the heap, we wait.
//
WAIT_FOR_HEAP(npExactHeap);
LOCK_HEAP(npExactHeap);
//
// Searching for pointer...
//
for(dw = npExactHeap->cNumAlloc;dw;dw--)
{
pMem = GetPointer(npExactHeap->pPointers,dw-1);
if(pMemFree == pMem)
{
//
// Marking buffer as not allocated by HEAP API's.
//
GetExactHeaderInfo(pMem,&ExactHdr);
ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
SetExactHeaderInfo(pMem,&ExactHdr);
//
// Freeing memory...
//
if(FALSE == ExactFreePtr(pMem))
{
DBGOUT("ExactFreePtr failed.");
ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
SetExactHeaderInfo(pMem,&ExactHdr);
UNLOCK_HEAP(npExactHeap);
return FALSE;
}
//
// Exchanging this pointer and last pointer...
//
npExactHeap->cNumAlloc--;
pMem = GetPointer(npExactHeap->pPointers,npExactHeap->cNumAlloc);
SetPointer(npExactHeap->pPointers,dw-1,pMem);
UNLOCK_HEAP(npExactHeap);
return TRUE;
}
}
//
// Pointer was not found?!
//
DBGOUT("Pointer not found.");
UNLOCK_HEAP(npExactHeap);
return FALSE;
} // ExactHeapFreePtr()
//--------------------------------------------------------------------------;
//
// LPVOID ExactHeapReAllocPtr
//
// Description:
// Reallocates a buffer to different size or allocation flags.
//
// Note: Don't count on the pointer remaining the same; the pointer
// _WILL_ change.
//
// Arguments:
// HANDLE hHeap: Handle to heap.
//
// LPVOID pOldPtr: Buffer to reallocate.
//
// DWORD cbAlloc: New size of buffer (in bytes).
//
// UINT fuAlloc: New allocation flags (See GlobalAlloc).
//
// Return (LPVOID):
// Pointer to new buffer, or NULL if error occurs.
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
LPVOID ExactHeapReAllocPtr
(
HANDLE hHeap,
LPVOID pOldPtr,
DWORD cbAlloc,
UINT fuAlloc
)
{
NPEXACTHEAP npExactHeap;
EXACTHDR ExactHdr;
LPVOID pMem;
DWORD dw;
npExactHeap = (NPEXACTHEAP)hHeap;
//
// Checking if it is a bad pointer.
//
if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
{
DBGOUT("Bad hHeap.");
return NULL;
}
//
// Checking if it is a bad handle.
//
if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
{
DBGOUT("Bad hHeap.");
return NULL;
}
//
// If someone else has a hold of the heap, we wait.
//
WAIT_FOR_HEAP(npExactHeap);
LOCK_HEAP(npExactHeap);
//
// Searching for pointer...
//
for(dw = npExactHeap->cNumAlloc;dw;dw--)
{
pMem = GetPointer(npExactHeap->pPointers,dw-1);
if(pOldPtr == pMem)
{
//
// Marking buffer as not allocated by HEAP API's.
//
GetExactHeaderInfo(pMem,&ExactHdr);
ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
SetExactHeaderInfo(pMem,&ExactHdr);
//
// Doing ReAlloc...
//
pMem = ExactReAllocPtr(pOldPtr,cbAlloc,fuAlloc);
if(NULL == pMem)
{
DBGOUT("ExactReAllocPtr failed.");
UNLOCK_HEAP(npExactHeap);
return NULL;
}
//
// Marking buffer as allocated by HEAP API's.
//
GetExactHeaderInfo(pMem,&ExactHdr);
ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
SetExactHeaderInfo(pMem,&ExactHdr);
//
// Updating pointer...
//
SetPointer(npExactHeap->pPointers,dw-1,pMem);
UNLOCK_HEAP(npExactHeap);
return pMem;
}
}
//
// Pointer not found?!
//
DBGOUT("Pointer not found.");
UNLOCK_HEAP(npExactHeap);
return NULL;
} // ExactHeapReAllocPtr()
//--------------------------------------------------------------------------;
//
// DWORD ExactHeapSize
//
// Description:
// Gets the size of the buffer the pointer refers to.
//
// Arguments:
// HANDLE hHeap: Handle to heap.
//
// UINT fuSize: Flags to function (None defined).
//
// LPVOID pMemSize: Pointer to buffer in question.
//
// Return (DWORD):
// Size (in bytes) of buffer, or Zero if error occurs
//
// History:
// 08/11/94 Fwong Adding heap support.
//
//--------------------------------------------------------------------------;
DWORD ExactHeapSize
(
HANDLE hHeap,
UINT fuSize,
LPVOID pMemSize
)
{
NPEXACTHEAP npExactHeap;
LPVOID pMem;
DWORD dw;
npExactHeap = (NPEXACTHEAP)hHeap;
//
// Checking if it is a bad pointer.
//
if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
{
DBGOUT("Bad hHeap.");
return 0L;
}
//
// Checking if it is a bad handle.
//
if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
{
DBGOUT("Bad hHeap.");
return 0L;
}
//
// If someone else has a hold of the heap, we wait.
//
WAIT_FOR_HEAP(npExactHeap);
LOCK_HEAP(npExactHeap);
//
// Searching for pointer...
//
for(dw = npExactHeap->cNumAlloc;dw;dw--)
{
pMem = GetPointer(npExactHeap->pPointers,dw-1);
if(pMemSize == pMem)
{
UNLOCK_HEAP(npExactHeap);
return ExactSize(pMem);
}
}
//
// Pointer not found.
//
DBGOUT("Pointer not found.");
UNLOCK_HEAP(npExactHeap);
return 0L;
} // ExactHeapSize()