- 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).

svn path=/trunk/; revision=49069
This commit is contained in:
Aleksey Bragin 2010-10-09 12:49:30 +00:00
parent 60ede58f09
commit c76fdb3cd6

View file

@ -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 @@ typedef struct _HEAP_ENTRY_EXTRA
{
USHORT AllocatorBackTraceIndex;
USHORT TagIndex;
ULONG Settable;
ULONG_PTR Settable;
};
UINT64 ZeroInit;
};
@ -1153,7 +1154,7 @@ RtlpDestroyHeapSegment(PHEAP_SEGMENT Segment)
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 @@ RtlReAllocateHeap(HANDLE HeapPtr,
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 @@ RtlUnlockHeap(HANDLE HeapPtr)
/* 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,10 +3316,51 @@ RtlSetUserValueHeap(IN PVOID HeapHandle,
IN PVOID BaseAddress,
IN PVOID UserValue)
{
UNIMPLEMENTED;
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;
}
/*
* @implemented
*/
@ -3319,11 +3369,49 @@ NTAPI
RtlSetUserFlagsHeap(IN PVOID HeapHandle,
IN ULONG Flags,
IN PVOID BaseAddress,
IN ULONG UserFlags)
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;
}
/*
* @implemented
*/
@ -3335,10 +3423,58 @@ RtlGetUserInfoHeap(IN PVOID HeapHandle,
OUT PVOID *UserValue,
OUT PULONG UserFlags)
{
UNIMPLEMENTED;
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;
}
/*
* @unimplemented
*/