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.
385 lines
12 KiB
385 lines
12 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
ntrtlbuffer3.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Jay Krell (JayKrell) January 2002
|
|
|
|
Environment:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ntrtlbuffer3.h"
|
|
|
|
typedef struct _REVEAL_RTL_BYTE_BUFFER3 {
|
|
PREVEAL_RTL_BYTE_BUFFER3 Self; // for heap allocated "mini dynamic"
|
|
PVOID Buffer;
|
|
SIZE_T RequestedSize;
|
|
SIZE_T AllocatedSize;
|
|
PVOID StaticBuffer;
|
|
SIZE_T StaticBufferSize;
|
|
PCRTL_BUFFER3_ALLOCATOR Traits;
|
|
PVOID TraitsContext;
|
|
} REVEAL_RTL_BYTE_BUFFER3, *PREVEAL_RTL_BYTE_BUFFER3;
|
|
typedef const REVEAL_RTL_BYTE_BUFFER3 * PCREVEAL_RTL_BYTE_BUFFER3;
|
|
|
|
PREVEAL_RTL_BYTE_BUFFER3
|
|
RtlpRevealByteBuffer3(
|
|
PRTL_BYTE_BUFFER3 OpaqueBuffer
|
|
)
|
|
{
|
|
return ((PREVEAL_RTL_BYTE_BUFFER3)OpaqueBuffer)->Self;
|
|
}
|
|
|
|
RTL_BUFFER3_RETURN
|
|
FASTCALL
|
|
RtlInitByteBuffer3(
|
|
ULONG Flags,
|
|
SIZE_T SizeofBuffer,
|
|
PRTL_BYTE_BUFFER3 Buffer,
|
|
SIZE_T SizeofStaticBuffer,
|
|
PBYTE StaticBuffer,
|
|
SIZE_T SizeofTraits,
|
|
PCRTL_BUFFER3_ALLOCATOR Traits,
|
|
PVOID TraitsContext
|
|
)
|
|
{
|
|
RTL_BUFFER3_RETURN Ret;
|
|
PREVEAL_RTL_BYTE_BUFFER3 Revealed;
|
|
BOOL NewStaticWithMiniDynamic;
|
|
|
|
if (SizeofBuffer < sizeof(*Buffer))
|
|
{
|
|
if (SizeofBuffer < (sizeof(ULONG_PTR)))
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
if (Traits == NULL)
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
if (!RTL_CONTAINS_FIELD(Traits, SizeofTraits, CanAllocate))
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
if (!RTL_CONTAINS_FIELD(Traits, SizeofTraits, Allocate))
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
if (!Traits->CanAllocate(TraitsContext))
|
|
{
|
|
goto InvalidParameter;
|
|
}
|
|
NewStaticWithMiniDynamic = (StaticBuffer == NULL && SizeofStaticBuffer != 0);
|
|
RevealedSize = sizeof(*Revealed;
|
|
if (NewStaticWithMiniDynamic)
|
|
{
|
|
RevealedSize += SizeofStaticBuffer;
|
|
}
|
|
Revealed = (PREVEAL_RTL_BYTE_BUFFER3)Traits->Allocate(TraitsContext, RevealedSize);
|
|
if (Revealed == NULL)
|
|
{
|
|
if (NewStaticWithMiniDynamic)
|
|
{
|
|
NewStaticWithMiniDynamic = FALSE;
|
|
Revealed = (PREVEAL_RTL_BYTE_BUFFER3)Traits->Allocate(TraitsContext, sizeof(*Revealed));
|
|
}
|
|
if (Revealed == NULL)
|
|
{
|
|
goto CallbackError;
|
|
}
|
|
}
|
|
if (NewStaticWithMiniDynamic)
|
|
{
|
|
StaticBuffer = (PBYTE)(Revealed + 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Revealed = (PREVEAL_RTL_BYTE_BUFFER3)Buffer;
|
|
}
|
|
((PREVEAL_RTL_BYTE_BUFFER3)OpaqueBuffer)->Self = Revealed;
|
|
Revealed->StaticBuffer = StaticBuffer;
|
|
Revealed->StaticBufferSize = SizeofStaticBuffer;
|
|
Revealed->RequestedSize = 0;
|
|
Revealed->AllocatedSize = SizeofStaticBuffer;
|
|
Revealed->Buffer = StaticBuffer;
|
|
Revealed->Traits = Traits;
|
|
Revealed->TraitsContext = TraitsContext;
|
|
|
|
Ret = RTL_BUFFER3_SUCCESS;
|
|
Exit:
|
|
return Ret;
|
|
|
|
InvalidParameter:
|
|
Ret = RTL_BUFFER3_INVALID_PARAMETER;
|
|
goto Exit;
|
|
CallbackError:
|
|
Ret = RTL_BUFFER3_CALLBACK_ERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
BOOL FASTCALL RtlBuffer3Allocator_CanAllocate_False(PVOID VoidContext) { return FALSE; }
|
|
BOOL FASTCALL RtlBuffer3Allocator_CanAllocate_True(PVOID VoidContext) { return TRUE; }
|
|
BOOL FASTCALL RtlBuffer3Allocator_CanReallocate_False(PVOID VoidContext) { return FALSE; }
|
|
BOOL FASTCALL RtlBuffer3Allocator_CanReallocate_True(PVOID VoidContext) { return TRUE; }
|
|
|
|
#if defined(_WINBASE_)
|
|
|
|
#define RtlpBuffer3Allocator_Win32HeapGetHeap(c) \
|
|
(((c) != NULL && (c)->UsePrivateHeap) ? (c)->PrivateHeap : GetProcessHeap())
|
|
|
|
#define RtlpBuffer3Allocator_Win32HeapGetError(c) \
|
|
(((c) != NULL && (c)->UsePrivateError) ? (c)->PrivateOutOfMemoryError : ERROR_NO_MEMORY)
|
|
|
|
#define RtlpBuffer3Allocator_Win32HeapGetFlags(c) \
|
|
(((c) != NULL) ? (c)->HeapFlags : 0)
|
|
|
|
#define RtlpBuffer3Allocator_Win32HeapSetLastError(c) \
|
|
(((c) == NULL || (c)->DoNotSetLastError) ? ((void)0) : SetLastError(RtlpBuffer3Allocator_Win32HeapGetError(c)))
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_Win32HeapAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
p = HeapAlloc(RtlpBuffer3Allocator_Win32HeapGetHeap(Context), RtlpBuffer3Allocator_Win32HeapGetFlags(Context), NumberOfBytes);
|
|
if (p == NULL)
|
|
RtlpBuffer3Allocator_Win32HeapSetLastError(Context);
|
|
return p;
|
|
}
|
|
|
|
VOID FASTCALL RtlBuffer3Allocator_Win32HeapFree(PVOID VoidContext, PVOID Pointer);
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
HeapFree(RtlpBuffer3Allocator_Win32HeapGetHeap(Context), RtlpBuffer3Allocator_Win32HeapGetFlags(Context), Pointer);
|
|
}
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_Win32HeapReallocate(PVOID VoidContext, PVOID OldPointer, SIZE_T NewSize)
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
p = HeapReAlloc(RtlpBuffer3Allocator_Win32HeapGetHeap(Context), RtlpBuffer3Allocator_Win32HeapGetFlags(Context), OldPointer, NewSize);
|
|
if (p == NULL)
|
|
RtlpBuffer3Allocator_Win32HeapSetLastError(Context);
|
|
return p;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(_NTRTL_) || defined(_NTURTL_)
|
|
|
|
#if RTLBUFFER3_KERNELMODE
|
|
|
|
#define RtlpBuffer3Allocator_NtHeapGetHeap(c) \
|
|
(ASSERT((c) != NULL), ASSERT((c)->UsePrivateHeap), ASSERT((c)->PrivateHeap != NULL), (c)->PrivateHeap)
|
|
|
|
#define RtlpBuffer3Allocator_NtHeapGetFlags(c) \
|
|
(ASSERT((c) != NULL), (c)->HeapFlags)
|
|
|
|
#else
|
|
|
|
#define RtlpBuffer3Allocator_NtHeapGetHeap(c) \
|
|
(((c) != NULL && (c)->UsePrivateHeap) ? (c)->PrivateHeap : RtlProcessHeap())
|
|
|
|
#define RtlpBuffer3Allocator_NtHeapGetFlags(c) \
|
|
(((c) != NULL) ? (c)->HeapFlags : 0)
|
|
|
|
#endif
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtHeapAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
p = RtlAllocateHeap(RtlpBuffer3Allocator_NtHeapGetHeap(Context), RtlpBuffer3Allocator_NtHeapGetFlags(Context), NumberOfBytes);
|
|
|
|
return p;
|
|
}
|
|
|
|
VOID FASTCALL RtlBuffer3Allocator_NtHeapFree(PVOID VoidContext, PVOID Pointer);
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
RtlFreeHeap(RtlpBuffer3Allocator_NtHeapGetHeap(Context), RtlpBuffer3Allocator_NtHeapGetFlags(Context), Pointer);
|
|
}
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtHeapReallocate(PVOID VoidContext, PVOID OldPointer, SIZE_T NewSize)
|
|
{
|
|
#if RTLBUFFER3_KERNELMODE || !defined(_NTURTL_)
|
|
return NULL;
|
|
#else
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
p = RtlReAllocateHeap(RtlpBuffer3Allocator_NtHeapGetHeap(Context), RtlpBuffer3Allocator_NtHeapGetFlags(Context), OldPointer, NewSize);
|
|
|
|
return p;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
SIZE_T FASTCALL * RtlBuffer3Allocator_FixedAllocationSize(PVOID VoidContext, SIZE_T CurrentAllocatedSize, SIZE_T RequiredSize)
|
|
{
|
|
return CurrentAllocatedSize;
|
|
}
|
|
|
|
SIZE_T FASTCALL * RtlBuffer3Allocator_DoublingAllocationSize(PVOID VoidContext, SIZE_T CurrentAllocatedSize, SIZE_T RequiredSize)
|
|
{
|
|
CurrentAllocatedSize += CurrentAllocatedSize;
|
|
return (RequiredSize >= CurrentAllocatedSize) ? RequiredSize : CurrentAllocatedSize;
|
|
}
|
|
|
|
SIZE_T FASTCALL * RtlBuffer3Allocator_MinimumAlocationSize(PVOID VoidContext, SIZE_T CurrentAllocatedSize, SIZE_T RequiredSize)
|
|
{
|
|
return RequiredSize;
|
|
}
|
|
|
|
//
|
|
// RtlAllocateStringRoutine is not exported outside of ntoskrnl.exe and ntdll.dll.
|
|
// RtlFreeStringRoutine is exported directly enough via RtlFreeUnicodeString.
|
|
//
|
|
// see base\ntdll\ldrinit.c and base\ntos\ex\pool.c for the definitions
|
|
// of RtlAllocateStringRoutine and RtlFreeStringRoutine.
|
|
//
|
|
|
|
VOID FASTCALL RtlBuffer3Allocator_NtStringFree(PVOID VoidContext, PVOID Pointer)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
UnicodeString.Buffer = (PWSTR)Pointer;
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
}
|
|
|
|
#if RTLBUFFER3_NTKERNEL || RTLBUFFER3_NTDLL
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtStringAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
return (*RtlAllocateStringRoutine)(NumberOfBytes);
|
|
}
|
|
|
|
#elif RTLBUFFER3_USERMODE
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtStringAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
return RtlAllocateHeap(RtlProcessHeap(), 0, NumberOfBytes);
|
|
}
|
|
|
|
#elif RTLBUFFER3_KERNELMODE
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtStringAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
#undef ExAllocatePoolWithTag
|
|
return ExAllocatePoolWithTag(PagedPool,NumberOfBytes,'grtS');
|
|
}
|
|
|
|
#endif
|
|
|
|
#if RTLBUFFER3_KERNELMODE && (defined(_EX_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTOSP_) || defined(_WDM_) || defined(_NTHAL_))
|
|
|
|
#define RtlpBuffer3Allocator_NtkernelPool_GetWhichFunction(c) \
|
|
(((c) != NULL) ? (c)->WhichFunction : RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL)
|
|
|
|
#define RtlpBuffer3Allocator_NtkernelPool_GetTag(c) \
|
|
(((c) != NULL) ? (c)->Tag : 0)
|
|
|
|
#define RtlpBuffer3Allocator_NtkernelPool_GetType(c) \
|
|
(((c) != NULL) ? (c)->Type : NonPagedPool)
|
|
|
|
#define RtlpBuffer3Allocator_NtkernelPool_GetPriority(c) \
|
|
(((c) != NULL) ? (c)->Priority : NormalPoolPriority)
|
|
|
|
#undef ExAllocatePoolWithTag
|
|
#undef ExAllocatePool
|
|
#undef ExAllocatePoolWithQuota
|
|
#undef ExAllocatePoolWithQuotaTag
|
|
#undef ExFreePool
|
|
#undef ExFreePoolWithTag
|
|
|
|
PVOID FASTCALL RtlBuffer3Allocator_NtkernelPoolAllocate(PVOID VoidContext, SIZE_T NumberOfBytes)
|
|
{
|
|
PVOID p;
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
switch (RtlpBuffer3Allocator_NtkernelPool_GetWhichFunction(Context))
|
|
{
|
|
default:
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL:
|
|
p = ExAllocatePool(
|
|
RtlpBuffer3Allocator_NtkernelPool_GetType(Context),
|
|
NumberOfBytes
|
|
);
|
|
break;
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_TAG:
|
|
p = ExAllocatePoolWithTag(
|
|
RtlpBuffer3Allocator_NtkernelPool_GetType(Context),
|
|
NumberOfBytes,
|
|
RtlpBuffer3Allocator_NtkernelPool_GetTag(Context)
|
|
);
|
|
break;
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_QUOTA:
|
|
p = ExAllocatePoolWithQuota(
|
|
RtlpBuffer3Allocator_NtkernelPool_GetType(Context),
|
|
NumberOfBytes
|
|
);
|
|
break;
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_QUOTA_TAG:
|
|
p = ExAllocatePoolWithQuotaTag(
|
|
RtlpBuffer3Allocator_NtkernelPool_GetType(Context),
|
|
NumberOfBytes,
|
|
RtlpBuffer3Allocator_NtkernelPool_GetTag(Context)
|
|
);
|
|
break;
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_TAG_PRIORITY:
|
|
p = ExAllocatePoolWithTagPriority(
|
|
RtlpBuffer3Allocator_NtkernelPool_GetType(Context),
|
|
NumberOfBytes,
|
|
RtlpBuffer3Allocator_NtkernelPool_GetTag(Context),
|
|
RtlpBuffer3Allocator_NtkernelPool_GetPriority(Context)
|
|
);
|
|
break;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
VOID FASTCALL RtlBuffer3Allocator_NtKernelPoolFree(PVOID VoidContext, PVOID Pointer)
|
|
{
|
|
PRTL_BUFFER3_ALLOCATOR_WIN32HEAP Context;
|
|
//
|
|
// ExFreePool/ExAllocatePoolWithTag, pretty unique among allocators, does not accept NULL.
|
|
//
|
|
if (Pointer == NULL)
|
|
return;
|
|
|
|
Context = (PRTL_BUFFER3_ALLOCATOR_WIN32HEAP)VoidContext;
|
|
|
|
switch (RtlpBuffer3Allocator_NtkernelPool_GetWhichFunction(Context))
|
|
{
|
|
default:
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL:
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_QUOTA:
|
|
ExFreePool(Pointer);
|
|
break;
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_TAG:
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_QUOTA_TAG:
|
|
case RTL_BUFFER3_ALLOCATOR_NTKERNELPOOL_ALLOCATE_EX_ALLOCATE_POOL_WITH_TAG_PRIORITY:
|
|
ExAllocatePoolWithTag(Pointer);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif
|