Fix prototype of RtlCreateHeap and respect the CommitRoutine if passed. Also fix the heap manager to be usable by kernel mode code.

svn path=/trunk/; revision=16939
This commit is contained in:
Filip Navara 2005-08-01 10:19:22 +00:00
parent f928348d93
commit 73113cc87d
6 changed files with 147 additions and 63 deletions

View file

@ -81,10 +81,10 @@ STDCALL
RtlCreateHeap( RtlCreateHeap(
IN ULONG Flags, IN ULONG Flags,
IN PVOID BaseAddress OPTIONAL, IN PVOID BaseAddress OPTIONAL,
IN ULONG SizeToReserve OPTIONAL, IN SIZE_T SizeToReserve OPTIONAL,
IN ULONG SizeToCommit OPTIONAL, IN SIZE_T SizeToCommit OPTIONAL,
IN PVOID Lock OPTIONAL, IN PVOID Lock OPTIONAL,
IN PRTL_HEAP_DEFINITION Definition OPTIONAL IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL
); );
DWORD DWORD

View file

@ -109,6 +109,15 @@ typedef VOID
PVOID Parameter PVOID Parameter
); );
#ifndef _NTIFS_
typedef NTSTATUS
(NTAPI * PRTL_HEAP_COMMIT_ROUTINE) (
IN PVOID Base,
IN OUT PVOID *CommitAddress,
IN OUT PSIZE_T CommitSize
);
#endif
/* TYPES *********************************************************************/ /* TYPES *********************************************************************/
typedef unsigned short RTL_ATOM; typedef unsigned short RTL_ATOM;
@ -219,12 +228,6 @@ typedef struct _MODULE_INFORMATION
ULONG ModuleCount; ULONG ModuleCount;
DEBUG_MODULE_INFORMATION ModuleEntry[1]; DEBUG_MODULE_INFORMATION ModuleEntry[1];
} MODULE_INFORMATION, *PMODULE_INFORMATION; } MODULE_INFORMATION, *PMODULE_INFORMATION;
typedef struct _RTL_HEAP_DEFINITION
{
ULONG Length;
ULONG Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
/* END REVIEW AREA */ /* END REVIEW AREA */
#ifdef _INC_EXCPT #ifdef _INC_EXCPT
@ -399,6 +402,22 @@ typedef struct _RTL_ATOM_TABLE
PRTL_ATOM_TABLE_ENTRY Buckets[1]; PRTL_ATOM_TABLE_ENTRY Buckets[1];
} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE; } RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;
#ifndef _NTIFS_
typedef struct _RTL_HEAP_PARAMETERS {
ULONG Length;
SIZE_T SegmentReserve;
SIZE_T SegmentCommit;
SIZE_T DeCommitFreeBlockThreshold;
SIZE_T DeCommitTotalFreeThreshold;
SIZE_T MaximumAllocationSize;
SIZE_T VirtualMemoryThreshold;
SIZE_T InitialCommit;
SIZE_T InitialReserve;
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
SIZE_T Reserved[2];
} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
#endif
/* Let Kernel Drivers use this */ /* Let Kernel Drivers use this */
#ifndef _WINBASE_ #ifndef _WINBASE_
typedef struct _SYSTEMTIME typedef struct _SYSTEMTIME

View file

@ -96,7 +96,7 @@ typedef struct tagHEAP
RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */ RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */
ULONG flags; /* Heap flags */ ULONG flags; /* Heap flags */
ULONG magic; /* Magic number */ ULONG magic; /* Magic number */
UCHAR filler[4]; /* Make multiple of 8 bytes */ PRTL_HEAP_COMMIT_ROUTINE commitRoutine;
} }
HEAP, *PHEAP; HEAP, *PHEAP;
@ -301,12 +301,19 @@ HEAP_Commit(SUBHEAP *subheap,
address = (PVOID)((char *)subheap + subheap->commitSize); address = (PVOID)((char *)subheap + subheap->commitSize);
commitsize = size - subheap->commitSize; commitsize = size - subheap->commitSize;
Status = NtAllocateVirtualMemory(NtCurrentProcess(), if (subheap->heap->commitRoutine != NULL)
&address, {
0, Status = subheap->heap->commitRoutine(subheap->heap, &address, &commitsize);
&commitsize, }
MEM_COMMIT, else
PAGE_EXECUTE_READWRITE); {
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
&address,
0,
&commitsize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
}
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT( "Could not commit %08lx bytes at %p for heap %p\n", DPRINT( "Could not commit %08lx bytes at %p for heap %p\n",
@ -321,6 +328,7 @@ HEAP_Commit(SUBHEAP *subheap,
} }
#if 0
/*********************************************************************** /***********************************************************************
* HEAP_Decommit * HEAP_Decommit
* *
@ -356,7 +364,7 @@ static inline BOOLEAN HEAP_Decommit( SUBHEAP *subheap, PVOID ptr, ULONG flags )
subheap->commitSize -= decommitsize; subheap->commitSize -= decommitsize;
return TRUE; return TRUE;
} }
#endif
/*********************************************************************** /***********************************************************************
* HEAP_CreateFreeBlock * HEAP_CreateFreeBlock
@ -504,27 +512,14 @@ static void HEAP_ShrinkBlock(SUBHEAP *subheap, ARENA_INUSE *pArena, ULONG size)
* HEAP_InitSubHeap * HEAP_InitSubHeap
*/ */
static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags, static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags,
ULONG commitSize, ULONG totalSize ) ULONG commitSize, ULONG totalSize,
PRTL_HEAP_PARAMETERS Parameters )
{ {
SUBHEAP *subheap = (SUBHEAP *)address; SUBHEAP *subheap = (SUBHEAP *)address;
FREE_LIST_ENTRY *pEntry; FREE_LIST_ENTRY *pEntry;
int i; int i;
NTSTATUS Status; NTSTATUS Status;
/* Commit memory */
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&address,
0,
(PULONG)&commitSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Could not commit %08lx bytes for sub-heap %p\n",
commitSize, address);
return FALSE;
}
/* Fill the sub-heap structure */ /* Fill the sub-heap structure */
subheap = (PSUBHEAP)address; subheap = (PSUBHEAP)address;
@ -550,6 +545,10 @@ static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags,
heap->next = NULL; heap->next = NULL;
heap->flags = flags; heap->flags = flags;
heap->magic = HEAP_MAGIC; heap->magic = HEAP_MAGIC;
if (Parameters)
heap->commitRoutine = Parameters->CommitRoutine;
else
heap->commitRoutine = NULL;
/* Build the free lists */ /* Build the free lists */
@ -570,6 +569,27 @@ static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags,
RtlInitializeCriticalSection( &heap->critSection ); RtlInitializeCriticalSection( &heap->critSection );
} }
/* Commit memory */
if (heap->commitRoutine)
{
Status = heap->commitRoutine(heap, &address, &commitSize);
}
else
{
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&address,
0,
&commitSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
}
if (!NT_SUCCESS(Status))
{
DPRINT("Could not commit %08lx bytes for sub-heap %p\n",
commitSize, address);
return FALSE;
}
/* Create the first free block */ /* Create the first free block */
HEAP_CreateFreeBlock( subheap, (PUCHAR)subheap + subheap->headerSize, HEAP_CreateFreeBlock( subheap, (PUCHAR)subheap + subheap->headerSize,
@ -586,8 +606,9 @@ static BOOLEAN HEAP_InitSubHeap( HEAP *heap, PVOID address, ULONG flags,
*/ */
static PSUBHEAP static PSUBHEAP
HEAP_CreateSubHeap(PVOID BaseAddress, HEAP_CreateSubHeap(PVOID BaseAddress,
HEAP *heap, ULONG flags, HEAP *heap, ULONG flags,
ULONG commitSize, ULONG totalSize ) ULONG commitSize, ULONG totalSize,
PRTL_HEAP_PARAMETERS Parameters )
{ {
PVOID address; PVOID address;
NTSTATUS Status; NTSTATUS Status;
@ -621,8 +642,9 @@ HEAP_CreateSubHeap(PVOID BaseAddress,
/* Initialize subheap */ /* Initialize subheap */
if (!HEAP_InitSubHeap( heap? heap : (HEAP *)address, if (!HEAP_InitSubHeap( heap ? heap : (HEAP *)address,
address, flags, commitSize, totalSize )) address, flags, commitSize, totalSize,
Parameters ))
{ {
if (!BaseAddress) if (!BaseAddress)
{ {
@ -690,7 +712,7 @@ static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, ULONG size,
* might get assigned all remaining free space in HEAP_ShrinkBlock() */ * might get assigned all remaining free space in HEAP_ShrinkBlock() */
size += sizeof(SUBHEAP) + sizeof(ARENA_FREE) + HEAP_MIN_BLOCK_SIZE; size += sizeof(SUBHEAP) + sizeof(ARENA_FREE) + HEAP_MIN_BLOCK_SIZE;
if (!(subheap = HEAP_CreateSubHeap( NULL, heap, heap->flags, size, if (!(subheap = HEAP_CreateSubHeap( NULL, heap, heap->flags, size,
max( HEAP_DEF_SIZE, size ) ))) max( HEAP_DEF_SIZE, size ), NULL )))
return NULL; return NULL;
DPRINT("created new sub-heap %p of %08lx bytes for heap %p\n", DPRINT("created new sub-heap %p of %08lx bytes for heap %p\n",
@ -1055,10 +1077,10 @@ static BOOLEAN HEAP_IsRealArena(
HANDLE STDCALL HANDLE STDCALL
RtlCreateHeap(ULONG flags, RtlCreateHeap(ULONG flags,
PVOID BaseAddress, PVOID BaseAddress,
ULONG maxSize, SIZE_T maxSize,
ULONG initialSize, SIZE_T initialSize,
PVOID Unknown, PVOID Lock,
PRTL_HEAP_DEFINITION Definition) PRTL_HEAP_PARAMETERS Parameters)
{ {
SUBHEAP *subheap; SUBHEAP *subheap;
HEAP *heapPtr; HEAP *heapPtr;
@ -1070,20 +1092,24 @@ RtlCreateHeap(ULONG flags,
maxSize = HEAP_DEF_SIZE; maxSize = HEAP_DEF_SIZE;
flags |= HEAP_GROWABLE; flags |= HEAP_GROWABLE;
} }
if (!(subheap = HEAP_CreateSubHeap( BaseAddress, NULL, flags, initialSize, maxSize ))) if (!(subheap = HEAP_CreateSubHeap( BaseAddress, NULL, flags, initialSize,
maxSize, Parameters )))
{ {
return 0; return 0;
} }
/* link it into the per-process heap list */ if (RtlpGetMode() == UserMode)
RtlEnterCriticalSection (&RtlpProcessHeapsListLock); {
/* link it into the per-process heap list */
RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
heapPtr = subheap->heap; heapPtr = subheap->heap;
heapPtr->next = (HEAP*)NtCurrentPeb()->ProcessHeaps; heapPtr->next = (HEAP*)NtCurrentPeb()->ProcessHeaps;
NtCurrentPeb()->ProcessHeaps = (HANDLE)heapPtr; NtCurrentPeb()->ProcessHeaps = (HANDLE)heapPtr;
NtCurrentPeb()->NumberOfHeaps++; NtCurrentPeb()->NumberOfHeaps++;
RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
}
return (HANDLE)subheap; return (HANDLE)subheap;
} }
@ -1112,18 +1138,21 @@ RtlDestroyHeap(HANDLE heap) /* [in] Handle of heap */
if (!heapPtr) if (!heapPtr)
return heap; return heap;
if (heap == NtCurrentPeb()->ProcessHeap) if (RtlpGetMode() == UserMode)
return heap; /* cannot delete the main process heap */ {
if (heap == NtCurrentPeb()->ProcessHeap)
return heap; /* cannot delete the main process heap */
/* remove it from the per-process list */ /* remove it from the per-process list */
RtlEnterCriticalSection (&RtlpProcessHeapsListLock); RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps;
while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next; while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next;
if (*pptr) *pptr = (*pptr)->next; if (*pptr) *pptr = (*pptr)->next;
NtCurrentPeb()->NumberOfHeaps--; NtCurrentPeb()->NumberOfHeaps--;
RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
}
RtlDeleteCriticalSection( &heapPtr->critSection ); RtlDeleteCriticalSection( &heapPtr->critSection );
subheap = &heapPtr->subheap; subheap = &heapPtr->subheap;

View file

@ -22,11 +22,6 @@
#define DENORMALIZE(x,addr) {if(x) x=(PVOID)((ULONG_PTR)(x)-(ULONG_PTR)(addr));} #define DENORMALIZE(x,addr) {if(x) x=(PVOID)((ULONG_PTR)(x)-(ULONG_PTR)(addr));}
#define ALIGN(x,align) (((ULONG)(x)+(align)-1UL)&(~((align)-1UL))) #define ALIGN(x,align) (((ULONG)(x)+(align)-1UL)&(~((align)-1UL)))
KPROCESSOR_MODE
RtlpGetMode();
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/

View file

@ -29,6 +29,7 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
extern PVOID RtlpAllocateMemory(UINT Bytes, ULONG Tag); extern PVOID RtlpAllocateMemory(UINT Bytes, ULONG Tag);
extern VOID RtlpFreeMemory(PVOID Mem, ULONG Tag); extern VOID RtlpFreeMemory(PVOID Mem, ULONG Tag);
extern KPROCESSOR_MODE RtlpGetMode();
#define RtlpAllocateStringMemory RtlpAllocateMemory #define RtlpAllocateStringMemory RtlpAllocateMemory
#define RtlpFreeStringMemory RtlpFreeMemory #define RtlpFreeStringMemory RtlpFreeMemory

View file

@ -1486,6 +1486,27 @@ typedef struct _READ_LIST {
#endif #endif
typedef NTSTATUS
(NTAPI * PRTL_HEAP_COMMIT_ROUTINE) (
IN PVOID Base,
IN OUT PVOID *CommitAddress,
IN OUT PSIZE_T CommitSize
);
typedef struct _RTL_HEAP_PARAMETERS {
ULONG Length;
SIZE_T SegmentReserve;
SIZE_T SegmentCommit;
SIZE_T DeCommitFreeBlockThreshold;
SIZE_T DeCommitTotalFreeThreshold;
SIZE_T MaximumAllocationSize;
SIZE_T VirtualMemoryThreshold;
SIZE_T InitialCommit;
SIZE_T InitialReserve;
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
SIZE_T Reserved[2];
} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
NTKERNELAPI NTKERNELAPI
BOOLEAN BOOLEAN
NTAPI NTAPI
@ -2170,6 +2191,18 @@ FsRtlCopyWrite (
IN PDEVICE_OBJECT DeviceObject IN PDEVICE_OBJECT DeviceObject
); );
NTKERNELAPI
PVOID
NTAPI
RtlCreateHeap (
IN ULONG Flags,
IN PVOID HeapBase OPTIONAL,
IN SIZE_T ReserveSize OPTIONAL,
IN SIZE_T CommitSize OPTIONAL,
IN PVOID Lock OPTIONAL,
IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL
);
NTKERNELAPI NTKERNELAPI
BOOLEAN BOOLEAN
NTAPI NTAPI
@ -2199,6 +2232,13 @@ FsRtlDeregisterUncProvider (
IN HANDLE Handle IN HANDLE Handle
); );
NTKERNELAPI
PVOID
NTAPI
RtlDestroyHeap(
IN PVOID HeapHandle
);
NTKERNELAPI NTKERNELAPI
VOID VOID
NTAPI NTAPI