/* Biased pointer macros */
#define IS_BIASED_POINTER(ptr) ((ULONG_PTR)(ptr) & 1)
#define POINTER_REMOVE_BIAS(ptr) ((ULONG_PTR)(ptr) & ~(ULONG_PTR)1)
-#define POINTER_ADD_BIAS(ptr) ((ULONG_PTR)(ptr) & 1)
+#define POINTER_ADD_BIAS(ptr) ((ULONG_PTR)(ptr) | 1)
ULONG RtlpDphBreakOptions = 0;//0xFFFFFFFF;
PVOID Ptr,
SIZE_T Size)
{
- UNIMPLEMENTED;
- return NULL;
+ PDPH_HEAP_ROOT DphRoot;
+ PDPH_HEAP_BLOCK Node = NULL, AllocatedNode;
+ BOOLEAN Biased = FALSE, UseNormalHeap = FALSE, OldBlockPageHeap = TRUE;
+ ULONG DataSize, ValidationInfo;
+ PVOID NewAlloc = NULL;
+
+ /* Check requested size */
+ if (Size > 0x7FF00000)
+ {
+ DPRINT1("extreme size request\n");
+
+ /* Generate an exception if needed */
+ if (Flags & HEAP_GENERATE_EXCEPTIONS) RtlpDphRaiseException(STATUS_NO_MEMORY);
+
+ return NULL;
+ }
+
+ /* Unbias the pointer if necessary */
+ if (IS_BIASED_POINTER(HeapPtr))
+ {
+ HeapPtr = (PVOID)POINTER_REMOVE_BIAS(HeapPtr);
+ Biased = TRUE;
+ }
+
+ /* Get a pointer to the heap root */
+ DphRoot = RtlpDphPointerFromHandle(HeapPtr);
+ if (!DphRoot) return NULL;
+
+ /* Acquire the heap lock */
+ RtlpDphPreProcessing(DphRoot, Flags);
+
+ /* Perform internal validation if specified by flags */
+ if (RtlpDphDebugOptions & DPH_DEBUG_INTERNAL_VALIDATE)
+ {
+ RtlpDphInternalValidatePageHeap(DphRoot, NULL, 0);
+ }
+
+ /* Add heap flags */
+ Flags |= DphRoot->HeapFlags;
+
+ /* Exit with NULL right away if inplace is specified */
+ if (Flags & HEAP_REALLOC_IN_PLACE_ONLY)
+ {
+ /* Release the lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Generate an exception if needed */
+ if (Flags & HEAP_GENERATE_EXCEPTIONS) RtlpDphRaiseException(STATUS_NO_MEMORY);
+
+ return NULL;
+ }
+
+ /* Try to get node of the allocated block */
+ AllocatedNode = RtlpDphFindBusyMemory(DphRoot, Ptr);
+
+ if (!AllocatedNode)
+ {
+ /* This block was not found in page heap, try a normal heap instead */
+ //RtlpDphNormalHeapFree();
+ ASSERT(FALSE);
+ OldBlockPageHeap = FALSE;
+ }
+
+ /* Check the block */
+ if (!(DphRoot->ExtraFlags & DPH_EXTRA_CHECK_UNDERRUN))
+ {
+ if (!RtlpDphIsPageHeapBlock(DphRoot, AllocatedNode->pUserAllocation, &ValidationInfo, TRUE))
+ {
+ RtlpDphReportCorruptedBlock(DphRoot, 3, AllocatedNode->pUserAllocation, ValidationInfo);
+ }
+ }
+
+ /* Remove old one from the busy list */
+ RtlpDphRemoveFromBusyList(DphRoot, AllocatedNode);
+
+ if (!Biased && !RtlpDphShouldAllocateInPageHeap(DphRoot, Size))
+ {
+ // FIXME: Use normal heap
+ ASSERT(FALSE);
+ UseNormalHeap = TRUE;
+ }
+ else
+ {
+ /* Now do a trick: bias the pointer and call our allocate routine */
+ NewAlloc = RtlpPageHeapAllocate((PVOID)POINTER_ADD_BIAS(HeapPtr), Flags, Size);
+ }
+
+ if (!NewAlloc)
+ {
+ /* New allocation failed, put the block back (if it was found in page heap) */
+ RtlpDphPlaceOnBusyList(DphRoot, AllocatedNode);
+
+ /* Release the lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Perform validation again if required */
+ if (RtlpDphDebugOptions & DPH_DEBUG_INTERNAL_VALIDATE)
+ {
+ RtlpDphInternalValidatePageHeap(DphRoot, NULL, 0);
+ }
+
+ /* Generate an exception if needed */
+ if (Flags & HEAP_GENERATE_EXCEPTIONS) RtlpDphRaiseException(STATUS_NO_MEMORY);
+
+ return NULL;
+ }
+
+ /* Copy contents of the old block */
+ if (AllocatedNode->nUserRequestedSize > Size)
+ DataSize = Size;
+ else
+ DataSize = AllocatedNode->nUserRequestedSize;
+
+ if (DataSize != 0) RtlCopyMemory(NewAlloc, Ptr, DataSize);
+
+ /* Copy user flags and values */
+ if (!UseNormalHeap)
+ {
+ /* Get the node of the new block */
+ Node = RtlpDphFindBusyMemory(DphRoot, NewAlloc);
+ ASSERT(Node != NULL);
+
+ /* Set its values/flags */
+ Node->UserValue = AllocatedNode->UserValue;
+ if (Flags & HEAP_SETTABLE_USER_FLAGS)
+ Node->UserFlags = Flags & HEAP_SETTABLE_USER_FLAGS;
+ else
+ Node->UserFlags = AllocatedNode->UserFlags;
+ }
+
+ if (!OldBlockPageHeap)
+ {
+ /* Weird scenario, investigate */
+ ASSERT(FALSE);
+ }
+
+ /* Mark the old block as no access */
+ if (AllocatedNode->nVirtualAccessSize != 0)
+ {
+ RtlpDphProtectVm(AllocatedNode->pVirtualBlock, AllocatedNode->nVirtualAccessSize, PAGE_NOACCESS);
+ }
+
+ /* And place it on the free list */
+ RtlpDphPlaceOnFreeList(DphRoot, AllocatedNode);
+
+ // FIXME: Capture stack traces if needed
+ AllocatedNode->StackTrace = NULL;
+
+ /* Finally allocation is done, perform validation again if required */
+ if (RtlpDphDebugOptions & DPH_DEBUG_INTERNAL_VALIDATE && !Biased)
+ {
+ RtlpDphInternalValidatePageHeap(DphRoot, NULL, 0);
+ }
+
+ /* Release the lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ DPRINT("Allocated new user block pointer: %p\n", NewAlloc);
+
+ /* Return pointer to user allocation */
+ return NewAlloc;
}
BOOLEAN NTAPI
PVOID *UserValue,
PULONG UserFlags)
{
- UNIMPLEMENTED;
- return FALSE;
+ PDPH_HEAP_ROOT DphRoot;
+ PDPH_HEAP_BLOCK Node;
+
+ /* Get a pointer to the heap root */
+ DphRoot = RtlpDphPointerFromHandle(HeapHandle);
+ if (!DphRoot) return FALSE;
+
+ /* Add heap flags */
+ Flags |= DphRoot->HeapFlags;
+
+ /* Acquire the heap lock */
+ RtlpDphPreProcessing(DphRoot, Flags);
+
+ /* Find busy memory */
+ Node = RtlpDphFindBusyMemory(DphRoot, BaseAddress);
+
+ if (!Node)
+ {
+ /* This block was not found in page heap, try a normal heap instead */
+ //RtlpDphNormalHeapGetUserInfo();
+ ASSERT(FALSE);
+ return FALSE;
+ }
+
+ /* Get user values and flags and store them in user provided pointers */
+ if (UserValue) *UserValue = Node->UserValue;
+ if (UserFlags) *UserFlags = Node->UserFlags;
+
+ /* Leave the heap lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Return success */
+ return TRUE;
}
BOOLEAN NTAPI
PVOID BaseAddress,
PVOID UserValue)
{
- UNIMPLEMENTED;
- return FALSE;
+ PDPH_HEAP_ROOT DphRoot;
+ PDPH_HEAP_BLOCK Node;
+
+ /* Get a pointer to the heap root */
+ DphRoot = RtlpDphPointerFromHandle(HeapHandle);
+ if (!DphRoot) return FALSE;
+
+ /* Add heap flags */
+ Flags |= DphRoot->HeapFlags;
+
+ /* Acquire the heap lock */
+ RtlpDphPreProcessing(DphRoot, Flags);
+
+ /* Find busy memory */
+ Node = RtlpDphFindBusyMemory(DphRoot, BaseAddress);
+
+ if (!Node)
+ {
+ /* This block was not found in page heap, try a normal heap instead */
+ //RtlpDphNormalHeapSetUserValue();
+ ASSERT(FALSE);
+ return FALSE;
+ }
+
+ /* Get user values and flags and store them in user provided pointers */
+ Node->UserValue = UserValue;
+
+ /* Leave the heap lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Return success */
+ return TRUE;
}
BOOLEAN
ULONG UserFlagsReset,
ULONG UserFlagsSet)
{
- UNIMPLEMENTED;
- return FALSE;
+ PDPH_HEAP_ROOT DphRoot;
+ PDPH_HEAP_BLOCK Node;
+
+ /* Get a pointer to the heap root */
+ DphRoot = RtlpDphPointerFromHandle(HeapHandle);
+ if (!DphRoot) return FALSE;
+
+ /* Add heap flags */
+ Flags |= DphRoot->HeapFlags;
+
+ /* Acquire the heap lock */
+ RtlpDphPreProcessing(DphRoot, Flags);
+
+ /* Find busy memory */
+ Node = RtlpDphFindBusyMemory(DphRoot, BaseAddress);
+
+ if (!Node)
+ {
+ /* This block was not found in page heap, try a normal heap instead */
+ //RtlpDphNormalHeapSetUserFlags();
+ ASSERT(FALSE);
+ return FALSE;
+ }
+
+ /* Get user values and flags and store them in user provided pointers */
+ Node->UserFlags &= ~(UserFlagsReset);
+ Node->UserFlags |= UserFlagsSet;
+
+ /* Leave the heap lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Return success */
+ return TRUE;
}
SIZE_T NTAPI
-RtlpPageHeapSize(HANDLE HeapPtr,
+RtlpPageHeapSize(HANDLE HeapHandle,
ULONG Flags,
- PVOID Ptr)
+ PVOID BaseAddress)
{
- UNIMPLEMENTED;
- return 0;
+ PDPH_HEAP_ROOT DphRoot;
+ PDPH_HEAP_BLOCK Node;
+ SIZE_T Size;
+
+ /* Get a pointer to the heap root */
+ DphRoot = RtlpDphPointerFromHandle(HeapHandle);
+ if (!DphRoot) return -1;
+
+ /* Add heap flags */
+ Flags |= DphRoot->HeapFlags;
+
+ /* Acquire the heap lock */
+ RtlpDphPreProcessing(DphRoot, Flags);
+
+ /* Find busy memory */
+ Node = RtlpDphFindBusyMemory(DphRoot, BaseAddress);
+
+ if (!Node)
+ {
+ /* This block was not found in page heap, try a normal heap instead */
+ //RtlpDphNormalHeapSize();
+ ASSERT(FALSE);
+ return -1;
+ }
+
+ /* Get heap block size */
+ Size = Node->nUserRequestedSize;
+
+ /* Leave the heap lock */
+ RtlpDphPostProcessing(DphRoot);
+
+ /* Return user requested size */
+ return Size;
}
/* EOF */