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.
 
 
 
 
 
 

248 lines
6.5 KiB

#include "nt.h"
#include "ntdef.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "ntrtl.h"
#include "sxs-rtl.h"
#include "skiplist.h"
#include "stringpool.h"
NTSTATUS
RtlAllocateStringInPool(
ULONG ulFlags,
PRTL_STRING_POOL pStringPool,
PUNICODE_STRING pusOutbound,
SIZE_T ulByteCount
)
{
NTSTATUS status;
ULONG idx;
PRTL_STRING_POOL_FRAME pFrameWithFreeSpace = NULL;
RtlZeroMemory(pusOutbound, sizeof(*pusOutbound));
if (!ARGUMENT_PRESENT(pStringPool) || !ARGUMENT_PRESENT(pusOutbound) || (ulByteCount >= 0xFFFF) ) {
return STATUS_INVALID_PARAMETER;
}
//
// Zing through frames in the string pool looking for a frame with
// enough bytes open
//
for (idx = 0; idx < pStringPool->ulFramesCount; idx++) {
status = RtlIndexIntoGrowingList(
&pStringPool->FrameList,
idx,
(PVOID*)&pFrameWithFreeSpace,
FALSE);
if (!NT_SUCCESS(status)) {
return status;
}
//
// There's space in this frame!
//
if (pFrameWithFreeSpace->cbRegionAvailable >= ulByteCount) {
break;
}
}
//
// Frame not found, index one past the current limit, implicitly (potentially)
// allocating into the growing list
//
if (pFrameWithFreeSpace == NULL) {
status = RtlIndexIntoGrowingList(
&pStringPool->FrameList,
pStringPool->ulFramesCount,
(PVOID*)&pFrameWithFreeSpace,
TRUE);
if (!NT_SUCCESS(status)) {
return status;
}
//
// Requested byte count is larger than the bytes in a new region? Bump up the
// size of new regions to twice this size
//
if (ulByteCount > pStringPool->cbBytesInNewRegion) {
pStringPool->cbBytesInNewRegion = ulByteCount * 2;
}
status = pStringPool->Allocator.pfnAlloc(
pStringPool->cbBytesInNewRegion,
(PVOID*)&pFrameWithFreeSpace->pvRegion,
pStringPool->Allocator.pvContext);
if (!NT_SUCCESS(status)) {
return STATUS_NO_MEMORY;
}
pFrameWithFreeSpace->pvNextAvailable = pFrameWithFreeSpace->pvRegion;
pFrameWithFreeSpace->cbRegionAvailable = pStringPool->cbBytesInNewRegion;
}
//
// Sanity checking
//
ASSERT(pFrameWithFreeSpace != NULL);
ASSERT(pFrameWithFreeSpace->cbRegionAvailable >= ulByteCount);
//
// Bookkeeping in the frame
//
pFrameWithFreeSpace->cbRegionAvailable -= ulByteCount;
pFrameWithFreeSpace->pvNextAvailable = (PVOID)(((ULONG_PTR)pFrameWithFreeSpace->pvNextAvailable) + ulByteCount);
//
// Set up the outbound thing
//
pusOutbound->Buffer = pFrameWithFreeSpace->pvNextAvailable;
pusOutbound->MaximumLength = (USHORT)ulByteCount;
pusOutbound->Length = 0;
return STATUS_SUCCESS;
}
NTSTATUS
RtlDestroyStringPool(
PRTL_STRING_POOL pStringPool
)
{
NTSTATUS status;
PRTL_STRING_POOL_FRAME pFrame = NULL;
ULONG ul;
//
// Zing through frames and deallocate those that weren't allocated
// inline with the pool
//
for (ul = 0; ul < pStringPool->ulFramesCount; ul++) {
status = RtlIndexIntoGrowingList(
&pStringPool->FrameList,
ul,
(PVOID*)&pFrame,
FALSE);
if (!NT_SUCCESS(status)) {
return status;
}
if ((pFrame->ulFlags & RTL_STRING_POOL_FRAME_FLAG_REGION_INLINE) == 0) {
status = pStringPool->Allocator.pfnFree(pFrame->pvRegion, pStringPool->Allocator.pvContext);
pFrame->pvRegion = NULL;
pFrame->pvNextAvailable = NULL;
pFrame->cbRegionAvailable = 0;
}
}
//
// We're done, destroy the list itself
//
status = RtlDestroyGrowingList(&pStringPool->FrameList);
if (!NT_SUCCESS(status)) {
return status;
}
//
// No frames, list destroyed
//
pStringPool->ulFramesCount = 0;
//
// Great.
//
return STATUS_SUCCESS;
}
NTSTATUS
RtlCreateStringPool(
ULONG ulFlags,
PRTL_STRING_POOL pStringPool,
SIZE_T cbBytesInFrames,
PRTL_ALLOCATOR Allocator,
PVOID pvOriginalRegion,
SIZE_T cbOriginalRegion
)
{
NTSTATUS status;
//
// Ick. Heap allocation all the way
//
if ((cbOriginalRegion == 0) || (pvOriginalRegion == NULL)) {
status = RtlInitializeGrowingList(
&pStringPool->FrameList,
sizeof(RTL_STRING_POOL_FRAME),
20,
NULL,
0,
Allocator);
pStringPool->ulFramesCount = 0;
pStringPool->Allocator = *Allocator;
pStringPool->cbBytesInNewRegion = cbBytesInFrames;
return STATUS_SUCCESS;
}
//
// Good, space for at least one frame, donate the remainder to the list
//
else if (cbOriginalRegion >= sizeof(RTL_STRING_POOL_FRAME)) {
RTL_STRING_POOL_FRAME* pFirstFrame = NULL;
status = RtlInitializeGrowingList(
&pStringPool->FrameList,
sizeof(RTL_STRING_POOL_FRAME),
20,
pvOriginalRegion,
sizeof(RTL_STRING_POOL_FRAME),
Allocator);
pStringPool->ulFramesCount = pStringPool->FrameList.cInternalElements;
pStringPool->Allocator = *Allocator;
pStringPool->cbBytesInNewRegion = cbBytesInFrames;
if (pStringPool->ulFramesCount) {
status = RtlIndexIntoGrowingList(
&pStringPool->FrameList,
0,
(PVOID*)&pFirstFrame,
FALSE);
//
// Wierd...
//
if ((status == STATUS_NO_MEMORY) || (status == STATUS_NOT_FOUND)) {
pStringPool->ulFramesCount = 0;
}
else {
pFirstFrame->pvRegion = pFirstFrame->pvNextAvailable =
(PVOID)(((ULONG_PTR)pvOriginalRegion) + sizeof(RTL_STRING_POOL_FRAME));
pFirstFrame->cbRegionAvailable = cbOriginalRegion - sizeof(RTL_STRING_POOL_FRAME);
pFirstFrame->ulFlags = RTL_STRING_POOL_FRAME_FLAG_REGION_INLINE;
}
}
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}