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.
431 lines
9.6 KiB
431 lines
9.6 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
ntrtlbuffer2.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Jay Krell (JayKrell) January 2002
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ntrtlbuffer2.h"
|
|
#include "ntrtlbuffer2p.h"
|
|
|
|
#if DBG
|
|
VOID
|
|
FASTCALL
|
|
RtlpAssertBuffer2Consistency(
|
|
PPRIVATE_RTL_BUFFER2 Buffer
|
|
)
|
|
{
|
|
ASSERT(Buffer->AllocatedSize >= Buffer->RequestedSize);
|
|
if (Buffer->Buffer == Buffer->StaticBuffer) {
|
|
ASSERT(Buffer->AllocatedSize == Buffer->StaticBufferSize);
|
|
}
|
|
}
|
|
|
|
PVOID
|
|
FASTCALL
|
|
RtlpFindNonNullInPointerArray(
|
|
PVOID * PointerArray,
|
|
SIZE_T SizeOfArray
|
|
)
|
|
{
|
|
SIZE_T i;
|
|
PVOID p;
|
|
|
|
p = NULL;
|
|
for ( i = 0 ; i != SizeOfArray ; ++i )
|
|
{
|
|
p = PointerArray[i];
|
|
if (p != NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
NTSTATUS
|
|
FASTCALL
|
|
RtlpValidateBuffer2Class(
|
|
PPRIVATE_RTL_BUFFER2 Class
|
|
)
|
|
{
|
|
FN_PROLOG();
|
|
PVOID Allocate[5] = { NULL, NULL, NULL, NULL, NULL };
|
|
PVOID Free[2] = { NULL, NULL };
|
|
PRTL_BUFFER2_CLASS_UALLOCATOR u;
|
|
PVOID HeapHandle;
|
|
BOOL NeedHeapHandle;
|
|
BOOL Failed;
|
|
|
|
CHECK_PARAMETER(Buffer != NULL);
|
|
|
|
Failed = FALSE;
|
|
NeedHeapHandle = FALSE;
|
|
u = &Class->uAllocator;
|
|
|
|
switch (Class->AllocatorType)
|
|
{
|
|
default:
|
|
DbgPrint("%s: bad Class->AllocatorType.\n", __FUNCTION__);
|
|
Allocate[0] = (PVOID)1;
|
|
Free[0] = (PVOID)1;
|
|
Failed = TRUE;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_STRING_CALLBACKS:
|
|
Allocate[0] = u->NtrtlStringRoutines.Allocate;
|
|
Free[0] = u->NtrtlStringRoutines.Free;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_POOL_CALLBACKS:
|
|
#if defined(_EX_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTOSP_) || defined(_WDM_) || defined(_NTHAL_)
|
|
Allocate[0] = u->NtkernelPool.Allocate;
|
|
Allocate[1] = u->NtkernelPool.AllocateWithQuota;
|
|
Allocate[2] = u->NtkernelPool.AllocateWithTag;
|
|
Allocate[3] = u->NtkernelPool.AllocateWithQuotaTag;
|
|
Allocate[4] = u->NtkernelPool.AllocateWithTagPriority;
|
|
Free[0] = u->NtkernelPool.Free;
|
|
Free[1] = u->NtkernelPool.FreeWithTag;
|
|
|
|
#else
|
|
DbgPrint("%s: You need to compile this code with more headers.\n", __FUNCTION__);
|
|
ORIGINATE_INVALID_PARAMETER();
|
|
#endif
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_HEAP_CALLBACKS:
|
|
Allocate[0] = u->NtrtlHeap.Allocate;
|
|
Free[0] = u->NtrtlHeap.Free;
|
|
NeadHeapHandle = TRUE;
|
|
HeapHandle = u->NtrtlHeap.HeapHandle;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_HEAP_CALLBACKS:
|
|
Allocate[0] = u->Win32Heap.Allocate;
|
|
Free[0] = u->Win32Heap.Free;
|
|
NeadHeapHandle = TRUE;
|
|
HeapHandle = u->Win32Heap.HeapHandle;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_CRT_CALLBACKS:
|
|
Allocate[0] = u->Crt.malloc;
|
|
Free[0] = u->Crt.free;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_IMALLOC:
|
|
Allocate[0] = u->Malloc
|
|
Free[0] = u->Malloc;
|
|
break;
|
|
}
|
|
|
|
if (NeedHeapHandle && HeapHandle == NULL)
|
|
{
|
|
DbgPrint("%s: NeadHeapHandle && HeapHandle == NULL\n", __FUNCTION__);
|
|
Failed = TRUE;
|
|
}
|
|
// ensure we have an allocate and a free routine
|
|
if (RtlpFindNonNullInPointerArray(Allocate, RTL_NUMBER_OF(Allocate)) == NULL)
|
|
{
|
|
DbgPrint("%s: missing allocate routine\n", __FUNCTION__);
|
|
Failed = TRUE;
|
|
}
|
|
// ensure we have an allocate and a free routine
|
|
if (RtlpFindNonNullInPointerArray(Free, RTL_NUMBER_OF(Free)) == NULL)
|
|
{
|
|
DbgPrint("%s: missing free routine\n", __FUNCTION__);
|
|
Failed = TRUE;
|
|
}
|
|
|
|
if (Failed)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
FN_EPILOG();
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
RtlpBuffer2ClassFree(
|
|
PRTL_BUFFER2_CLASS Class,
|
|
PVOID p
|
|
)
|
|
{
|
|
PRTL_BUFFER2_CLASS_UALLOCATOR u;
|
|
|
|
if (p == NULL) {
|
|
goto Exit;
|
|
}
|
|
|
|
u = &Class->uAllocator;
|
|
switch (Class->AllocatorType)
|
|
{
|
|
default:
|
|
DbgPrint("%s: bad Class->AllocatorType.\n", __FUNCTION__);
|
|
ORIGINATE_INVALID_PARAMETER();
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_STRING_CALLBACKS:
|
|
(*u->NtrtlStringRoutines.Free)(
|
|
p);
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_POOL_CALLBACKS:
|
|
#if defined(_EX_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTOSP_) || defined(_WDM_) || defined(_NTHAL_)
|
|
ASSERT(u->NtkernelPool.FreeWithTag != NULL || u->NtkernelPool.Free != NULL);
|
|
if (u->NtkernelPool.FreeWithTag != NULL)
|
|
{
|
|
(*u->NtkernelPool.FreeWithTag)(p, u->NtkernelPool.Tag);
|
|
}
|
|
else if (u->NtkernelPool.Free != NULL)
|
|
{
|
|
(*u->NtkernelPool.Free)(p);
|
|
}
|
|
#else
|
|
DbgPrint("%s: You need to compile this code with more headers.\n", __FUNCTION__);
|
|
ORIGINATE_INVALID_PARAMETER();
|
|
#endif
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_HEAP_CALLBACKS:
|
|
(*u->NtrtlHeap.Free)(
|
|
u->NtrtlHeap.HeapHandle,
|
|
0,
|
|
p);
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_HEAP_CALLBACKS:
|
|
(*u->Win32Heap.Free)(
|
|
u->Win32Heap.HeapHandle,
|
|
0,
|
|
p);
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_CRT_CALLBACKS:
|
|
(*u->Crt.Free)(
|
|
p);
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_IMALLOC:
|
|
break;
|
|
}
|
|
|
|
Exit:
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
RtlpBuffer2ClassCanReallocate(
|
|
PRTL_BUFFER2_CLASS Class
|
|
)
|
|
{
|
|
PVOID * pp;
|
|
PRTL_BUFFER2_CLASS_UALLOCATOR u;
|
|
|
|
u = &Class->uAllocator;
|
|
|
|
switch (Class->AllocatorType)
|
|
{
|
|
default:
|
|
ASSERT(FALSE);
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_STRING_CALLBACKS:
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_POOL_CALLBACKS:
|
|
pp = NULL; // FALSE
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_NTRTL_HEAP_CALLBACKS:
|
|
pp = (PVOID*)&u->NtrtlHeap.Reallocate;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_HEAP_CALLBACKS:
|
|
pp = (PVOID*)&u->Win32Heap.Reallocate;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_WIN32_CRT_CALLBACKS:
|
|
pp = (PVOID*)&u->Crt.Reallocate;
|
|
break;
|
|
|
|
case RTL_BUFFER2_CLASS_ALLOCATOR_IMALLOC:
|
|
pp = (PVOID*)&pp; // TRUE
|
|
break;
|
|
}
|
|
return (pp != NULL && *pp != NULL);
|
|
}
|
|
|
|
|
|
RETURN_TYPE
|
|
NTAPI
|
|
RtlEnsureBufferSizeEx2(
|
|
PRTL_BUFFER2 Buffer,
|
|
SIZE_T Size
|
|
OUT PVOID * p OPTIONAL
|
|
)
|
|
{
|
|
FN_PROLOG();
|
|
|
|
CHECK_PARAMETER(Buffer != NULL);
|
|
if (p != NULL) {
|
|
*p = NULL;
|
|
}
|
|
|
|
Ret = RtlEnsureBufferSize2(Buffer, Size);
|
|
if (MY_FAILED(Ret)) {
|
|
goto Exit;
|
|
}
|
|
if (p != NULL) {
|
|
*p = RtlpGetBuffer2(Buffer);
|
|
}
|
|
|
|
FN_EPILOG();
|
|
}
|
|
|
|
PVOID
|
|
FASTCALL
|
|
RtlpBuffer2ClassAllocate(
|
|
PRTL_BUFFER2_CLASS Class,
|
|
SIZE_T Size
|
|
)
|
|
{
|
|
PVOID p;
|
|
|
|
switch (p
|
|
p = NULL;
|
|
Exit:
|
|
return p;
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
RtlpBuffer2ClassError(
|
|
PRTL_BUFFER2_CLASS Class
|
|
)
|
|
{
|
|
}
|
|
|
|
RETURN_TYPE
|
|
NTAPI
|
|
RtlpInitBuffer2(
|
|
PPRIVATE_RTL_BUFFER2 Buffer,
|
|
struct _RTL_BUFFER_CLASS * Class,
|
|
PVOID StaticBuffer,
|
|
SIZE_T StaticBufferSize
|
|
)
|
|
{
|
|
FN_PROLOG();
|
|
|
|
Ret = RtlpValidateBuffer2Class(Class);
|
|
if (MY_FAILED(Ret)) {
|
|
goto Exit;
|
|
}
|
|
if (StaticBufferSize != 0 && StaticBuffer == NULL) {
|
|
//
|
|
// This could mean do an initial allocation.
|
|
//
|
|
// Status = RtlpBuffer2ClassAllocate(Class, StaticBufferSize, &StaticBuffer);
|
|
// if (!NT_SUCCESS(Status)) {
|
|
// goto Exit;
|
|
// }
|
|
//
|
|
ORIGINATE_INVALID_PARAMETER();
|
|
}
|
|
Buffer->Buffer = StaticBuffer;
|
|
Buffer->StaticBuffer = StaticBuffer;
|
|
Buffer->StaticBufferSize = StaticBufferSize;
|
|
Buffer->AllocatedSize = StaticBufferSize;
|
|
Buffer->RequestedSize = 0;
|
|
Buffer->Class = Class;
|
|
|
|
RtlpAssertBuffer2Consistency(Buffer);
|
|
|
|
FN_EPILOG();
|
|
}
|
|
|
|
RETURN_TYPE
|
|
NTAPI
|
|
RtlInitBuffer2(
|
|
PRTL_BUFFER2 OpaqueBuffer,
|
|
struct _RTL_BUFFER_CLASS * Class,
|
|
PVOID StaticBuffer,
|
|
SIZE_T StaticBufferSize
|
|
)
|
|
{
|
|
return RtlpInitBuffer2((PPRIVATE_RTL_BUFFER2)OpaqueBuffer, Class, StaticBuffer, StaticBufferSize);
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
RtlpFreeBuffer2(
|
|
PPRIVATE_RTL_BUFFER2 Buffer
|
|
)
|
|
{
|
|
FN_PROLOG();
|
|
PRIVATE_RTL_BUFFER2 Local;
|
|
|
|
RtlpAssertBuffer2Consistency(Buffer);
|
|
|
|
Local.StaticBuffer = Buffer->StaticBuffer;
|
|
Local.Buffer = Buffer->Buffer;
|
|
Local.Class = Buffer->Class;
|
|
|
|
if (Local.Buffer != Local.StaticBuffer) {
|
|
RtlpBuffer2ClassFree(Local.Class, Local.Buffer);
|
|
}
|
|
Ret = RtlpInitBuffer2(Buffer, Local.Class, Local.StaticBuffer, Buffer->StaticBufferSize);
|
|
ASSERT(MY_SUCCESS(Ret));
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
RtlFreeBuffer2(
|
|
PRTL_BUFFER2 OpaqueBuffer
|
|
)
|
|
{
|
|
RtlpFreeBuffer2((PPRIVATE_RTL_BUFFER2)OpaqueBuffer);
|
|
}
|
|
|
|
SIZE_T
|
|
FASTCALL
|
|
RtlGetAllocatedBufferSize2(
|
|
PRTL_BUFFER2 Buffer,
|
|
)
|
|
{
|
|
ASSERT(Buffer != NULL);
|
|
return RtlpGetAllocatedBufferSize2(Buffer);
|
|
}
|
|
|
|
SIZE_T
|
|
FASTCALL
|
|
RtlGetRequestedBufferSize2(
|
|
PRTL_BUFFER2 Buffer,
|
|
OUT PSIZE_T Size
|
|
)
|
|
{
|
|
ASSERT(Buffer != NULL);
|
|
return RtlpGetRequestedBufferSize2(Buffer);
|
|
}
|
|
|
|
PVOID
|
|
FASTCALL
|
|
RtlGetBuffer2(
|
|
PRTL_BUFFER2 Buffer
|
|
)
|
|
{
|
|
ASSERT(Buffer != NULL);
|
|
return RtlpGetBuffer2(Buffer);
|
|
}
|