Leaked source code of windows server 2003
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.
 
 
 
 
 
 

448 lines
18 KiB

// Ruler
// 1 2 3 4 5 6 7 8
//345678901234567890123456789012345678901234567890123456789012345678901234567890
/********************************************************************/
/* */
/* The standard layout. */
/* */
/* The standard layout for 'cpp' files in this code is as */
/* follows: */
/* */
/* 1. Include files. */
/* 2. Constants local to the class. */
/* 3. Data structures local to the class. */
/* 4. Data initializations. */
/* 5. Static functions. */
/* 6. Class functions. */
/* */
/* The constructor is typically the first function, class */
/* member functions appear in alphabetical order with the */
/* destructor appearing at the end of the file. Any section */
/* or function this is not required is simply omitted. */
/* */
/********************************************************************/
#include "InterfacePCH.hpp"
#include "DefaultHeap.hpp"
#include "Global.hpp"
#include "New.hpp"
#include "WindowsHeap.hpp"
/********************************************************************/
/* */
/* Constants local to the class. */
/* */
/* The constants supplied here are for common values. */
/* */
/********************************************************************/
CONST SBIT32 NoHeapSize = -1;
CONST SBIT32 ResizeDown = -64;
CONST SBIT32 StandardSize = (1024 * 1024);
/********************************************************************/
/* */
/* Data structures local to the class. */
/* */
/* We need to keep various information along with the heap */
/* so here we supply a structure to hold it all. */
/* */
/********************************************************************/
typedef struct
{
DWORD Flags;
DEFAULT_HEAP Rockall;
}
WINDOWS_HEAP;
/********************************************************************/
/* */
/* Create a new heap. */
/* */
/* Create a new heap and prepare it for use. If any problems */
/* are encountered the request is rejected. */
/* */
/********************************************************************/
extern "C" HANDLE WindowsHeapCreate
(
DWORD Flags,
DWORD InitialSize,
DWORD MaximumSize
)
{
//
// We do not support all the functionality with
// this interface so just reject any calls that
// require the unsupported features.
//
if ( MaximumSize <= 0 )
{
REGISTER WINDOWS_HEAP *WindowsHeap =
#ifdef NO_DEFAULT_HEAP
((WINDOWS_HEAP*) malloc( sizeof(WINDOWS_HEAP) ));
#else
((WINDOWS_HEAP*) DefaultHeap.New( sizeof(WINDOWS_HEAP) ));
#endif
//
// If we were unable to allocate space for
// the root of the heap then we exit.
//
if ( WindowsHeap != NULL )
{
//
// Save the flags for later calls.
//
WindowsHeap -> Flags = Flags;
//
// Call the heap constructor.
//
PLACEMENT_NEW( & WindowsHeap -> Rockall,DEFAULT_HEAP )
(
((SBIT32) (InitialSize + StandardSize)),
True,
False,
((BOOLEAN) ((Flags & HEAP_NO_SERIALIZE) == 0))
);
//
// Ensure the heap is initialized correctly.
//
if ( ! WindowsHeap -> Rockall.Corrupt() )
{ return ((HANDLE) WindowsHeap); }
else
{ free( WindowsHeap ); }
}
}
return NULL;
}
/********************************************************************/
/* */
/* Allocate memory. . */
/* */
/* Create a new memory allocation and verify it works. if */
/* not then throw an exception or return a status. */
/* */
/********************************************************************/
extern "C" LPVOID WindowsHeapAlloc( HANDLE Heap,DWORD Flags,DWORD Size )
{
REGISTER DWORD AllFlags =
(Flags | (((WINDOWS_HEAP*) Heap) -> Flags));
REGISTER void *NewMemory =
(
((WINDOWS_HEAP*) Heap) -> Rockall.New
(
Size,
NULL,
(AllFlags & HEAP_ZERO_MEMORY)
)
);
//
// If the caller has requested an exception when
// an error occurs. We will generate this instead
// of returning a status.
//
if ( (NewMemory == NULL) && (AllFlags & HEAP_GENERATE_EXCEPTIONS) )
{
SetLastError( ERROR_INVALID_PARAMETER );
RaiseException( STATUS_NO_MEMORY,0,0,NULL );
}
return NewMemory;
}
/********************************************************************/
/* */
/* Compact the heap. */
/* */
/* Compact the heap by returning any unallocated space to the */
/* operating system. This can prove to be very expensive if */
/* the space is later reclaimed. */
/* */
/********************************************************************/
extern "C" UINT WindowsHeapCompact( HANDLE Heap,DWORD Flags )
{
//
// We instruct the heap to return any available
// space to the operating system. If we later
// choose to regain this space it is very expensive
// so lets hope the user knew what he was doing.
//
((WINDOWS_HEAP*) Heap) -> Rockall.Truncate();
return 1;
}
/********************************************************************/
/* */
/* Free memory. */
/* */
/* Free a memory allocation so that the space may be recycled */
/* for subsequent memory allocation requests. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapFree( HANDLE Heap,DWORD Flags,LPVOID Memory )
{
//
// We release the memory allocation if it belongs to us.
// If not then we simply fail the request. Regardless,
// we are not negatively effected either way.
//
return ((BOOL) ((WINDOWS_HEAP*) Heap) -> Rockall.Delete( Memory ));
}
/********************************************************************/
/* */
/* Lock the heap. */
/* */
/* Lock the heap by claiming all of the associated heap locks. */
/* All the locks associated with a heap help make the heap */
/* scale well but are a big performance hit for this type of */
/* request. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapLock( HANDLE Heap )
{
//
// We have a whole fleet of locks assocaited with a heap.
// Asking to claim all of them is not smart in most cases.
// Nonetheless, this is part of the existing functionality
// so we support it.
//
(((WINDOWS_HEAP*) Heap) -> Rockall.LockAll());
return TRUE;
}
/********************************************************************/
/* */
/* Reallocate memory. */
/* */
/* Reallocate a portion of memory and possibly copy the data */
/* to the enlarged memory area. */
/* */
/********************************************************************/
extern "C" LPVOID WindowsHeapReAlloc
(
HANDLE Heap,
DWORD Flags,
LPVOID Memory,
DWORD Size
)
{
REGISTER DWORD AllFlags =
(Flags | (((WINDOWS_HEAP*) Heap) -> Flags));
REGISTER void *NewMemory =
(
((WINDOWS_HEAP*) Heap) -> Rockall.Resize
(
Memory,
Size,
((AllFlags & HEAP_REALLOC_IN_PLACE_ONLY) ? 0 : ResizeDown),
false,
(AllFlags & HEAP_ZERO_MEMORY)
)
);
//
// If the caller has requested an exception when
// an error occurs. We will generate this instead
// of returning a status.
//
if ( (NewMemory == NULL) && (AllFlags & HEAP_GENERATE_EXCEPTIONS) )
{
SetLastError( ERROR_INVALID_PARAMETER );
RaiseException( STATUS_NO_MEMORY,0,0,NULL );
}
return NewMemory;
}
/********************************************************************/
/* */
/* Reset the heap. */
/* */
/* Delete all outstanding memory allocations while leaving */
/* the structure of the heap in place ready for new memory */
/* allocation requests. */
/* */
/********************************************************************/
extern "C" VOID WindowsHeapReset( HANDLE Heap )
{
//
// We have been asked to delete all the outstanding
// memory allocations. This is significant and costly
// process. Nonetheless, the overhead is the same as
// around 20-30 delete requested so it can be worthwhile
// in a number of cases.
//
((WINDOWS_HEAP*) Heap) -> Rockall.DeleteAll();
}
/********************************************************************/
/* */
/* Allocation size. */
/* */
/* Although Rockall optionally supplies the allocation size */
/* when a new allocation is requested. Nonetheless, this has */
/* to be done the hard way with other interfaces. */
/* */
/********************************************************************/
extern "C" DWORD WindowsHeapSize( HANDLE Heap,DWORD Flags,LPVOID Memory )
{
AUTO INT Size;
//
// We have to go to quite a bit of trouble to figure
// out the allocation size. Unlike many other allocators
// we only keep track of each allocations using 2 bits.
// This combined with trying to establish that the allocation
// is not unallocated and sitting in the cache somewhere
// combine to make this quite expensive.
//
if ( ((WINDOWS_HEAP*) Heap) -> Rockall.Details( Memory,& Size ) )
{ return Size; }
else
{ return ((DWORD) NoHeapSize); }
}
/********************************************************************/
/* */
/* Unlock the heap. */
/* */
/* Unlock the heap and release all the associated heap locks. */
/* The multiple locks that need to be released make this quite */
/* an expensive request. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapUnlock( HANDLE Heap )
{
//
// We have a whole fleet of locks assocaited with a heap.
// Asking to claim all of them is not smart in most cases.
// Nonetheless, this is part of the existing functionality
// so we support it.
//
(((WINDOWS_HEAP*) Heap) -> Rockall.UnlockAll());
return TRUE;
}
/********************************************************************/
/* */
/* Validate the heap. */
/* */
/* Validate the heap or a specific heap allocation to ensure */
/* all is well. We have to go to quite a bit of trouble to */
/* figure this out so this call can be quite expensive. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapValidate( HANDLE Heap,DWORD Flags,LPVOID Memory )
{
//
// We have to go to quite a bit of trouble to figure
// out the allocation size. Unlike many other allocators
// we only keep track of each allocations using 2 bits.
// This combined with trying to establish that the allocation
// is not unallocated and sitting in the cache somewhere
// combine to make this quite expensive.
//
return (((WINDOWS_HEAP*) Heap) -> Rockall.Verify( Memory ));
}
/********************************************************************/
/* */
/* Walk the heap. */
/* */
/* Walk the heap and provide information about every allocated */
/* and unallocated portion of memory. Needless to say this is */
/* typically a long process and the request is not cheap. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapWalk( HANDLE Heap,LPPROCESS_HEAP_ENTRY Walk )
{
AUTO bool Active;
REGISTER BOOL Result =
(
((WINDOWS_HEAP*) Heap) -> Rockall.Walk
(
& Active,
((void**) & Walk -> lpData),
((int*) & Walk -> cbData)
)
);
//
// If we managed to find the next element we
// fill in all the other fields as needed.
//
if ( Result )
{
//
// Fill in all the addition fields just
// to be compatible with the existing
// functionality.
//
Walk -> cbOverhead = 0;
Walk -> iRegionIndex = 0;
Walk -> wFlags =
(
(Active)
? ((WORD) PROCESS_HEAP_ENTRY_BUSY)
: ((WORD) PROCESS_HEAP_UNCOMMITTED_RANGE)
);
}
return Result;
}
/********************************************************************/
/* */
/* Delete a heap. */
/* */
/* Delete a heap and release all the associated space. */
/* */
/********************************************************************/
extern "C" BOOL WindowsHeapDestroy( HANDLE Heap )
{
if ( ! ((WINDOWS_HEAP*) Heap) -> Rockall.Corrupt() )
{
//
// We do not appear to have damaged the heap
// so it should be safe to delete it.
//
PLACEMENT_DELETE( & ((WINDOWS_HEAP*) Heap) -> Rockall,DEFAULT_HEAP );
#ifdef NO_DEFAULT_HEAP
free( ((WINDOWS_HEAP*) Heap) );
#else
DefaultHeap.Delete( ((WINDOWS_HEAP*) Heap) );
#endif
return TRUE;
}
else
{ return FALSE; }
}