2020-09-30 17:17:25 +02:00

572 lines
12 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation
Module Name:
heap.c
Abstract:
Maps the Win32 heap APIs to the Rtl heap functions
--*/
#include "basedll.h"
#pragma hdrstop
//
// Handle of the default process heap.
//
HANDLE XapiProcessHeap;
HANDLE
WINAPI
HeapCreate(
DWORD flOptions,
SIZE_T dwInitialSize,
SIZE_T dwMaximumSize
)
/*++
Routine Description:
Creates a new heap
Arguments:
flOptions - either HEAP_GENERATE_EXCEPTIONS or HEAP_NO_SERIALIZE
dwInitialSize - initial heap size
dwMaximumSize - maximum heap size
Return Value:
Returns the new heap handle
--*/
{
HANDLE hHeap;
ULONG GrowthThreshold;
ULONG Flags;
Flags = (flOptions & (HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE)) | HEAP_CLASS_1;
GrowthThreshold = 0;
if (dwMaximumSize < PAGE_SIZE) {
if (dwMaximumSize == 0) {
GrowthThreshold = PAGE_SIZE * 16;
Flags |= HEAP_GROWABLE;
}
else {
dwMaximumSize = PAGE_SIZE;
}
}
if (GrowthThreshold == 0 && dwInitialSize > dwMaximumSize) {
dwMaximumSize = dwInitialSize;
}
hHeap = (HANDLE)RtlCreateHeap( Flags,
NULL,
dwMaximumSize,
dwInitialSize,
0,
NULL
);
if (hHeap == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
return( hHeap );
}
BOOL
WINAPI
HeapDestroy(
HANDLE hHeap
)
{
if (RtlDestroyHeap( (PVOID)hHeap ) == NULL ) {
return( TRUE );
}
else {
SetLastError( ERROR_INVALID_HANDLE );
return( FALSE );
}
}
BOOL
WINAPI
HeapFree(
HANDLE hHeap,
DWORD dwFlags,
LPVOID lpMem
)
{
return (BOOL) RtlFreeHeap( (PVOID)hHeap, dwFlags, lpMem );
}
#if DBG
BOOL
WINAPI
HeapValidate(
HANDLE hHeap,
DWORD dwFlags,
LPVOID lpMem
)
{
return RtlValidateHeap( hHeap, dwFlags, lpMem );
}
#endif // DBG
HANDLE
WINAPI
GetProcessHeap( VOID )
/*++
Routine Description:
Returns the handle for the process default heap (used with Local/GlobalXxxx functions)
Arguments:
Return Value:
Process heap handle (can be used with HeapAlloc/HeapFree/HeapSize functions)
--*/
{
return XapiProcessHeap;
}
#if DBG
WINBASEAPI
SIZE_T
WINAPI
HeapCompact(
HANDLE hHeap,
DWORD dwFlags
)
{
return RtlCompactHeap( hHeap, dwFlags );
}
WINBASEAPI
BOOL
WINAPI
HeapLock(
HANDLE hHeap
)
{
return RtlLockHeap( hHeap );
}
WINBASEAPI
BOOL
WINAPI
HeapUnlock(
HANDLE hHeap
)
{
return RtlUnlockHeap( hHeap );
}
WINBASEAPI
BOOL
WINAPI
HeapWalk(
HANDLE hHeap,
LPPROCESS_HEAP_ENTRY lpEntry
)
{
RTL_HEAP_WALK_ENTRY Entry;
NTSTATUS Status;
if (lpEntry->lpData == NULL) {
Entry.DataAddress = NULL;
Status = RtlWalkHeap( hHeap, &Entry );
}
else {
Entry.DataAddress = lpEntry->lpData;
Entry.SegmentIndex = lpEntry->iRegionIndex;
if (lpEntry->wFlags & PROCESS_HEAP_REGION) {
Entry.Flags = RTL_HEAP_SEGMENT;
}
else
if (lpEntry->wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) {
Entry.Flags = RTL_HEAP_UNCOMMITTED_RANGE;
Entry.DataSize = lpEntry->cbData;
}
else
if (lpEntry->wFlags & PROCESS_HEAP_ENTRY_BUSY) {
Entry.Flags = RTL_HEAP_BUSY;
}
else {
Entry.Flags = 0;
}
Status = RtlWalkHeap( hHeap, &Entry );
}
if (NT_SUCCESS( Status )) {
lpEntry->lpData = Entry.DataAddress;
lpEntry->cbData = (DWORD)Entry.DataSize;
lpEntry->cbOverhead = Entry.OverheadBytes;
lpEntry->iRegionIndex = Entry.SegmentIndex;
if (Entry.Flags & RTL_HEAP_BUSY) {
lpEntry->wFlags = PROCESS_HEAP_ENTRY_BUSY;
//
// DDESHARE and MOVEABLE are not meaningful on Xbox
//
#if 0
if (Entry.Flags & BASE_HEAP_FLAG_DDESHARE) {
lpEntry->wFlags |= PROCESS_HEAP_ENTRY_DDESHARE;
}
if (Entry.Flags & BASE_HEAP_FLAG_MOVEABLE) {
lpEntry->wFlags |= PROCESS_HEAP_ENTRY_MOVEABLE;
lpEntry->Block.hMem = (HLOCAL)Entry.Block.Settable;
}
#endif // 0
memset( lpEntry->Block.dwReserved, 0, sizeof( lpEntry->Block.dwReserved ) );
}
else
if (Entry.Flags & RTL_HEAP_SEGMENT) {
lpEntry->wFlags = PROCESS_HEAP_REGION;
lpEntry->Region.dwCommittedSize = Entry.Segment.CommittedSize;
lpEntry->Region.dwUnCommittedSize = Entry.Segment.UnCommittedSize;
lpEntry->Region.lpFirstBlock = Entry.Segment.FirstEntry;
lpEntry->Region.lpLastBlock = Entry.Segment.LastEntry;
}
else
if (Entry.Flags & RTL_HEAP_UNCOMMITTED_RANGE) {
lpEntry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
memset( &lpEntry->Region, 0, sizeof( lpEntry->Region ) );
}
else {
lpEntry->wFlags = 0;
}
return TRUE;
}
else {
XapiSetLastNTError( Status );
return FALSE;
}
}
#endif // DBG
HLOCAL
WINAPI
LocalAlloc(
UINT uFlags,
SIZE_T uBytes
)
/*++
Routine Description:
The LocalAlloc function allocates the specified number of bytes from the heap.
In the linear Win32 API environment, there is no difference between the
local heap and the global heap.
NOTE: Moveable memory is not implemented. LMEM_FIXED is always on.
Arguments:
UINT uFlags - allocation attributes
UINT uBytes - number of bytes to allocate
Return Value:
Returns pointer to newly allocated memory or NULL on failure.
--*/
{
#if DBG
// Validate flags
if (uFlags & (LMEM_MOVEABLE | LMEM_DISCARDABLE))
{
RIP("LocalAlloc() invalid parameter (uFlags)");
}
#endif // DBG
return (HLOCAL)RtlAllocateHeap(XapiProcessHeap,
(uFlags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0, (DWORD)uBytes);
}
HLOCAL
WINAPI
LocalReAlloc(
HLOCAL hMem,
SIZE_T uBytes,
UINT uFlags
)
/*++
Routine Description:
The LocalReAlloc function changes the size of a specified
local memory object. The size can increase or decrease.
NOTE: Since moveable memory isn't implemented, passing LMEM_MOVEABLE allows the handle
(pointer) value to change on return. If LMEM_MOVEABLE is not passed in and there is
no space following the memory block, the call may fail to grow the block size. Note
that this is the opposite sense of the HEAP_REALLOC_IN_PLACE_ONLY flag.
Arguments:
hMem - pointer to memory object to resize
uBytes - new size
uFlags - options for reallocation (same semantics as HeapReAlloc)
Return Value:
returns the new handle (may have changed) or NULL on failure.
--*/
{
#if DBG
// Validate flags
if (uFlags & (LMEM_DISCARDABLE | LMEM_MODIFY))
{
RIP("LocalReAlloc() invalid parameter (uFlags)");
}
#endif // DBG
return (HLOCAL)RtlReAllocateHeap(XapiProcessHeap,
(uFlags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0 +
(uFlags & LMEM_MOVEABLE) ? 0 : HEAP_REALLOC_IN_PLACE_ONLY,
(PVOID)hMem, (DWORD)uBytes);
}
SIZE_T
WINAPI
LocalSize(
HLOCAL hMem
)
/*++
Routine Description:
Returns the size of an allocation in bytes. Also implements GlobalSize()
Arguments:
hMem - pointer to memory
Return Value:
size or zero on error.
--*/
{
return (SIZE_T)RtlSizeHeap(XapiProcessHeap, 0, (LPVOID)hMem);
}
HLOCAL
WINAPI
LocalFree(
HLOCAL hMem
)
/*++
Routine Description:
The LocalFree function frees the specified local memory object and
invalidates its handle. Also implements GlobalFree().
Arguments:
hMem - handle of local memory object
Return Value:
If the function succeeds, the return value is NULL. If the function fails,
the return value is equal to the handle of the local memory object.
--*/
{
if (RtlFreeHeap(XapiProcessHeap, 0, (LPVOID)hMem))
return NULL;
else
return hMem;
}
WINBASEAPI
LPVOID
WINAPI
LocalLock(
IN HLOCAL hMem
)
/*++
Routine Description:
Maps a handle to a pointer. Since only fixed memory is supported,
the input value is returned. This function is unneccesary overhead
for applications to call. Note that no reference count is maintained.
Arguments:
hMem - memory handle
Return Value:
returns hMem cast to a pointer.
--*/
{
return (LPVOID)hMem;
}
WINBASEAPI
HLOCAL
WINAPI
LocalHandle(
IN LPCVOID pMem
)
/*++
Routine Description:
Maps a pointer to a handle. Since only fixed memory is supported,
the input value is returned. It is safe to assume that handles == pointers
for LocalXxxx functions.
Arguments:
pMem - memory pointer
Return Value:
returns pMem cast as a handle
--*/
{
return (HLOCAL)pMem;
}
WINBASEAPI
BOOL
WINAPI
LocalUnlock(
IN HLOCAL hMem
)
/*++
Routine Description:
Does nothing at all since only fixed memory is supported
Arguments:
hMem - memory handle
Return Value:
Always returns true
--*/
{
return TRUE;
}
HGLOBAL
WINAPI
GlobalAlloc(
UINT uFlags,
SIZE_T dwBytes
)
/*++
Routine Description:
The GlobalAlloc function allocates the specified number of bytes from the heap.
In the linear Win32 API environment, there is no difference between the
local heap and the global heap.
NOTE: Moveable memory is not implemented. GMEM_FIXED is always on.
Arguments:
UINT uFlags - allocation attributes
UINT uBytes - number of bytes to allocate
Return Value:
Returns pointer to newly allocated memory or NULL on failure.
--*/
{
#if DBG
// Validate flags (don't allow GMEM_MOVEABLE or GMEM_DISCARDABLE
// ignore all other flags--they should be completely benign)
if (uFlags & (GMEM_MOVEABLE | GMEM_DISCARDABLE))
{
RIP("GlobalAlloc() invalid parameter (uFlags)");
}
#endif // DBG
return (HLOCAL)RtlAllocateHeap(XapiProcessHeap,
(uFlags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0, (DWORD)dwBytes);
}
HGLOBAL
WINAPI
GlobalReAlloc(
HANDLE hMem,
SIZE_T uBytes,
UINT uFlags
)
/*++
Routine Description:
The GlobalReAlloc function changes the size of a specified
local memory object. The size can increase or decrease.
NOTE: Since moveable memory isn't implemented, passing GMEM_MOVEABLE allows the handle
(pointer) value to change on return. If GMEM_MOVEABLE is not passed in and there is
no space following the memory block, the call may fail to grow the block size. Note
that this is the opposite sense of the HEAP_REALLOC_IN_PLACE_ONLY flag.
Arguments:
hMem - pointer to memory object to resize
uBytes - new size
uFlags - options for reallocation (same semantics as HeapReAlloc)
Return Value:
returns the new handle (may have changed) or NULL on failure.
--*/
{
#if DBG
// Validate flags (don't allow GMEM_DISCARDABLE or GMEM_MODIFY, ignore others
// as they should be completely benign)
if (uFlags & (GMEM_DISCARDABLE | GMEM_MODIFY))
{
RIP("GlobalReAlloc() invalid parameter (uFlags)");
}
#endif // DBG
return (HLOCAL)RtlReAllocateHeap(XapiProcessHeap,
(uFlags & GMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0 +
(uFlags & GMEM_MOVEABLE) ? 0 : HEAP_REALLOC_IN_PLACE_ONLY,
(PVOID)hMem, (DWORD)uBytes);
}