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(
IN ULONG Flags,
IN PVOID BaseAddress OPTIONAL,
IN ULONG SizeToReserve OPTIONAL,
IN ULONG SizeToCommit OPTIONAL,
IN SIZE_T SizeToReserve OPTIONAL,
IN SIZE_T SizeToCommit OPTIONAL,
IN PVOID Lock OPTIONAL,
IN PRTL_HEAP_DEFINITION Definition OPTIONAL
IN PRTL_HEAP_PARAMETERS Parameters OPTIONAL
);
DWORD

View file

@ -109,6 +109,15 @@ typedef VOID
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 *********************************************************************/
typedef unsigned short RTL_ATOM;
@ -219,12 +228,6 @@ typedef struct _MODULE_INFORMATION
ULONG ModuleCount;
DEBUG_MODULE_INFORMATION ModuleEntry[1];
} MODULE_INFORMATION, *PMODULE_INFORMATION;
typedef struct _RTL_HEAP_DEFINITION
{
ULONG Length;
ULONG Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
/* END REVIEW AREA */
#ifdef _INC_EXCPT
@ -399,6 +402,22 @@ typedef struct _RTL_ATOM_TABLE
PRTL_ATOM_TABLE_ENTRY Buckets[1];
} 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 */
#ifndef _WINBASE_
typedef struct _SYSTEMTIME

View file

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

View file

@ -22,11 +22,6 @@
#define DENORMALIZE(x,addr) {if(x) x=(PVOID)((ULONG_PTR)(x)-(ULONG_PTR)(addr));}
#define ALIGN(x,align) (((ULONG)(x)+(align)-1UL)&(~((align)-1UL)))
KPROCESSOR_MODE
RtlpGetMode();
/* 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 VOID RtlpFreeMemory(PVOID Mem, ULONG Tag);
extern KPROCESSOR_MODE RtlpGetMode();
#define RtlpAllocateStringMemory RtlpAllocateMemory
#define RtlpFreeStringMemory RtlpFreeMemory

View file

@ -1486,6 +1486,27 @@ typedef struct _READ_LIST {
#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
BOOLEAN
NTAPI
@ -2170,6 +2191,18 @@ FsRtlCopyWrite (
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
BOOLEAN
NTAPI
@ -2199,6 +2232,13 @@ FsRtlDeregisterUncProvider (
IN HANDLE Handle
);
NTKERNELAPI
PVOID
NTAPI
RtlDestroyHeap(
IN PVOID HeapHandle
);
NTKERNELAPI
VOID
NTAPI