Author: fireball
Date: Sat Oct 9 12:49:30 2010
New Revision: 49069
URL:
http://svn.reactos.org/svn/reactos?rev=49069&view=rev
Log:
[HEAP]
- Implement setting/getting heap user values and flags (very easy provided heap design is
now proper). Amount of winetest failures is down to 12 (but 3 crashes in child
processes).
Modified:
trunk/reactos/lib/rtl/heap_rewrite.c
Modified: trunk/reactos/lib/rtl/heap_rewrite.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/heap_rewrite.c?rev…
==============================================================================
--- trunk/reactos/lib/rtl/heap_rewrite.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/heap_rewrite.c [iso-8859-1] Sat Oct 9 12:49:30 2010
@@ -12,6 +12,7 @@
http://binglongx.spaces.live.com/blog/cns!142CBF6D49079DE8!596.entry
http://www.phreedom.org/research/exploits/asn1-bitstring/
http://illmatics.com/Understanding_the_LFH.pdf
+
http://www.alex-ionescu.com/?p=18
*/
/* INCLUDES *****************************************************************/
@@ -243,7 +244,7 @@
{
USHORT AllocatorBackTraceIndex;
USHORT TagIndex;
- ULONG Settable;
+ ULONG_PTR Settable;
};
UINT64 ZeroInit;
};
@@ -1153,7 +1154,7 @@
if (Segment->SegmentFlags & HEAP_USER_ALLOCATED) return;
BaseAddress = Segment->BaseAddress;
- DPRINT1("Destroying segment %p, BA %p\n", Segment, BaseAddress);
+ DPRINT("Destroying segment %p, BA %p\n", Segment, BaseAddress);
/* Release virtual memory */
Status = ZwFreeVirtualMemory(NtCurrentProcess(),
@@ -2983,7 +2984,15 @@
Flags |= HEAP_SETTABLE_USER_VALUE | ((InUseEntry->Flags &
HEAP_ENTRY_SETTABLE_FLAGS) << 4);
- UNIMPLEMENTED;
+ /* Get pointer to the old extra data */
+ OldExtra = RtlpGetExtraStuffPointer(InUseEntry);
+
+ /* Save tag index if it was set */
+ if (OldExtra->TagIndex &&
+ !(OldExtra->TagIndex & HEAP_PSEUDO_TAG_FLAG))
+ {
+ Flags |= OldExtra->TagIndex << HEAP_TAG_SHIFT;
+ }
}
else if (InUseEntry->SmallTagIndex)
{
@@ -3131,7 +3140,7 @@
/* Check if it's really a heap */
if (Heap->Signature != HEAP_SIGNATURE) return FALSE;
- /* Lock if it's lockable */
+ /* Unlock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{
RtlLeaveHeapLock(Heap->LockVariable);
@@ -3307,8 +3316,49 @@
IN PVOID BaseAddress,
IN PVOID UserValue)
{
- UNIMPLEMENTED;
- return FALSE;
+ PHEAP Heap = (PHEAP)HeapHandle;
+ PHEAP_ENTRY HeapEntry;
+ PHEAP_ENTRY_EXTRA Extra;
+ BOOLEAN HeapLocked = FALSE;
+
+ /* Force flags */
+ Flags |= Heap->Flags;
+
+ /* Lock if it's lockable */
+ if (!(Heap->Flags & HEAP_NO_SERIALIZE))
+ {
+ RtlEnterHeapLock(Heap->LockVariable);
+ HeapLocked = TRUE;
+ }
+
+ /* Get a pointer to the entry */
+ HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
+
+ /* If it's a free entry - return error */
+ if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
+ {
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return FALSE;
+ }
+
+ /* Check if this entry has an extra stuff associated with it */
+ if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
+ {
+ /* Use extra to store the value */
+ Extra = RtlpGetExtraStuffPointer(HeapEntry);
+ Extra->Settable = (ULONG_PTR)UserValue;
+ }
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return TRUE;
}
/*
@@ -3319,9 +3369,47 @@
RtlSetUserFlagsHeap(IN PVOID HeapHandle,
IN ULONG Flags,
IN PVOID BaseAddress,
- IN ULONG UserFlags)
-{
- return FALSE;
+ IN ULONG UserFlagsReset,
+ IN ULONG UserFlagsSet)
+{
+ PHEAP Heap = (PHEAP)HeapHandle;
+ PHEAP_ENTRY HeapEntry;
+ BOOLEAN HeapLocked = FALSE;
+
+ /* Force flags */
+ Flags |= Heap->Flags;
+
+ /* Lock if it's lockable */
+ if (!(Heap->Flags & HEAP_NO_SERIALIZE))
+ {
+ RtlEnterHeapLock(Heap->LockVariable);
+ HeapLocked = TRUE;
+ }
+
+ /* Get a pointer to the entry */
+ HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
+
+ /* If it's a free entry - return error */
+ if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
+ {
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return FALSE;
+ }
+
+ /* Set / reset flags */
+ HeapEntry->Flags &= ~(UserFlagsReset >> 4);
+ HeapEntry->Flags |= (UserFlagsSet >> 4);
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return TRUE;
}
/*
@@ -3335,8 +3423,56 @@
OUT PVOID *UserValue,
OUT PULONG UserFlags)
{
- UNIMPLEMENTED;
- return FALSE;
+ PHEAP Heap = (PHEAP)HeapHandle;
+ PHEAP_ENTRY HeapEntry;
+ PHEAP_ENTRY_EXTRA Extra;
+ BOOLEAN HeapLocked = FALSE;
+
+ /* Force flags */
+ Flags |= Heap->Flags;
+
+ /* Lock if it's lockable */
+ if (!(Heap->Flags & HEAP_NO_SERIALIZE))
+ {
+ RtlEnterHeapLock(Heap->LockVariable);
+ HeapLocked = TRUE;
+ }
+
+ /* Get a pointer to the entry */
+ HeapEntry = (PHEAP_ENTRY)BaseAddress - 1;
+
+ /* If it's a free entry - return error */
+ if (!(HeapEntry->Flags & HEAP_ENTRY_BUSY))
+ {
+ RtlSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return FALSE;
+ }
+
+ /* Check if this entry has an extra stuff associated with it */
+ if (HeapEntry->Flags & HEAP_ENTRY_EXTRA_PRESENT)
+ {
+ /* Get pointer to extra data */
+ Extra = RtlpGetExtraStuffPointer(HeapEntry);
+
+ /* Pass user value */
+ if (UserValue)
+ *UserValue = (PVOID)Extra->Settable;
+
+ /* Decode and return user flags */
+ if (UserFlags)
+ *UserFlags = (HeapEntry->Flags & HEAP_ENTRY_SETTABLE_FLAGS) <<
4;
+ }
+
+ /* Release the heap lock if it was acquired */
+ if (HeapLocked)
+ RtlLeaveHeapLock(Heap->LockVariable);
+
+ return TRUE;
}
/*