RtlpDeCommitFreeBlock
VOID __stdcall RtlpDeCommitFreeBlock(_HEAP *Heap, _HEAP_FREE_ENTRY *FreeBlock, UINT64 FreeSize){
char v3;
char v4;
_HEAP_FREE_ENTRY *v5;
_HEAP *v6;
char v7;
unsigned __int64 v8;
_HEAP_UCR_DESCRIPTOR *v9;
_HEAP_FREE_ENTRY *v10;
_HEAP_SEGMENT *p_Segment;
UINT64 v12;
UINT64 v13;
UINT64 v14;
unsigned __int64 v15;
_LIST_ENTRY *i;
_LIST_ENTRY *v17;
_HEAP_FREE_ENTRY *v18;
INT64 v19;
__int64 v20;
__int64 v21;
INT64 v22;
_HEAP_UCR_DESCRIPTOR *v23;
_HEAP *v24;
bool v25;
_HEAP_UCR_DESCRIPTOR *v26;
unsigned __int64 v27;
UINT64 v28;
unsigned __int64 v29;
char *v30;
UINT64 v31;
bool v32;
INT64 v33;
_HEAP *v34;
_LIST_ENTRY *v35;
__int64 v36;
__int64 v37;
unsigned __int64 v38;
UINT64 v39;
char *v40;
UINT64 v41;
INT64 v42;
_HEAP *v43;
INT64 v44;
_HEAP_FREE_ENTRY *LastKnownEntry;
UINT64 *v46;
VOID *BaseAddress;
__int64 v48;
UINT64 Size;
_HEAP_UCR_DESCRIPTOR *UCRBlock;
__int64 v51[2];
UINT64 RegionSize;
UINT64 FreeSizea;
char v54;
v54 = v3;
FreeSizea = FreeSize;
v4 = 0;
v25 = (int(__fastcall *)(void *, void **, unsigned __int64 *))RtlpHeapKey == Heap->CommitRoutine;
v5 = FreeBlock;
v6 = Heap;
v51[0] = 0i64;
v48 = 0i64;
v7 = 0;
v54 = 0;
if( !v25 || FreeSize < Heap->DeCommitFreeBlockThreshold )
goto LABEL_80;
v8 = FreeSize + Heap->TotalFreeSize;
if( v8 < Heap->DeCommitTotalFreeThreshold
|| v8 < Heap->Counters.TotalMemoryCommitted >> (LOBYTE(Heap->TuningParameters.CommittThresholdShift) + 4) )
{
LABEL_79:
Heap = v6;
LABEL_80:
RtlpInsertFreeBlock(Heap, FreeBlock, FreeSize);
return;
}
v10 = RtlpCoalesceFreeBlocks(Heap, FreeBlock, &FreeSizea, (UINT64 *)v8, (UINT64 *)LastKnownEntry, v46);
if( v5->HeapEntry.UnpackedEntry.SegmentOffset )
{
v9 = (_HEAP_UCR_DESCRIPTOR *)((unsigned __int64)v5->HeapEntry.UnpackedEntry.SegmentOffset << 16);
p_Segment = (_HEAP_SEGMENT *)(((unsigned __int64)v5 & 0xFFFFFFFFFFFF0000ui64) - (_QWORD)v9 + 0x10000);
}
else
{
p_Segment = &v6->Segment;
}
v12 = FreeSizea;
v13 = (UINT64)v10 + 16 * FreeSizea;
if( *(_BYTE *)(v13 + 15) == 3 )
{
RtlpRemoveUCRBlock(v9);
v14 = *(_QWORD *)(v13 + 56);
v48 = *(_QWORD *)(v13 + 48);
Size = v14;
--p_Segment->NumberOfUnCommittedRanges;
p_Segment->NumberOfUnCommittedPages -= *(_QWORD *)(v13 + 56) >> 12;
v6->Counters.TotalMemoryCommitted += *(_QWORD *)(v13 + 56);
--v6->Counters.TotalUCRs;
v15 = *(_QWORD *)(v13 + 56);
if( v15 >= 0xFF000 )
{
v6->Counters.TotalMemoryLargeUCR -= v15;
v15 = *(_QWORD *)(v13 + 56);
}
v54 = 1;
v12 += (v15 >> 4) + 64;
v7 = 1;
FreeSizea = v12;
}
else
{
Size = 0i64;
}
if( v6->Encoding.UnpackedEntry.PreviousSize != v10->HeapEntry.UnpackedEntry.PreviousSize )
{
v35 = (_LIST_ENTRY *)(((unsigned __int64)&v10[129].FreeList.Blink + 7) & 0xFFFFFFFFFFFFF000ui64);
BaseAddress = v35;
if( v35 == &v10[2].FreeList )
{
v35 += 256;
BaseAddress = v35;
}
if( v7 )
{
v36 = 16 * v12;
v37 = (__int64)v10 + 16 * v12;
}
else
{
v36 = 16 * v12;
v37 = (__int64)&v10[-1] + 16 * v12;
}
v38 = v37 & 0xFFFFFFFFFFFFF000ui64;
if( v38 < (unsigned __int64)v35 )
{
if( RtlpHeapErrorHandlerThreshold >= 1 && v54 )
{
DbgPrint("(!TrailingUCR)");
RtlpHeapHandleError(v44);
}
goto LABEL_29;
}
v39 = v38 - (_QWORD)v35;
RegionSize = v39;
if( *(_BYTE *)(v13 + 15) != 3 && (!v39 || v39 < v6->DeCommitFreeBlockThreshold) )
{
LABEL_29:
FreeSize = v12;
LABEL_30:
FreeBlock = v10;
goto LABEL_79;
}
if( !v39
|| (++v6->Counters.DeCommitOps,
ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x4000ui64) >= 0) )
{
if( !v54 )
{
v40 = (char *)BaseAddress + RegionSize;
*(_WORD *)((char *)BaseAddress + RegionSize + 12) = v6->Encoding.UnpackedEntry.PreviousSize;
if( (char *)v10 + v36 == (char *)BaseAddress + RegionSize )
{
if( v6->EncodeFlagMask )
{
v40[11] = v40[8] ^ v40[9] ^ v40[10];
*((_DWORD *)v40 + 2) ^= v6->Encoding.UnpackedEntry.SubSegmentCode;
}
}
else
{
v40[15] = 0;
v40[10] = 0;
v41 = ((unsigned __int64)v10 + v36 - RegionSize - (_QWORD)BaseAddress) >> 4;
v32 = RtlpHeapErrorHandlerThreshold < 1;
*((_WORD *)v40 + 4) = v41;
if( !v32 && (unsigned __int16)v41 <= 1u )
{
DbgPrint("(LONG)FreeEntry->Size > 1");
RtlpHeapHandleError(v42);
}
v40[11] = 0;
v43 = p_Segment->Heap;
if( v43 != (_HEAP *)p_Segment )
{
if( ((unsigned __int64)(v40 - (char *)p_Segment) >> 16) + 1 >= 0xFE )
{
RtlpLogHeapFailure(heap_failure_entry_corruption, v43, v40, p_Segment, 0i64);
LOWORD(v41) = *((_WORD *)v40 + 4);
}
v4 = ((unsigned int)((_DWORD)v40 - (_DWORD)p_Segment) >> 16) + 1;
}
v40[14] = v4;
RtlpInsertFreeBlock(v6, (_HEAP_FREE_ENTRY *)v40, (unsigned __int16)v41);
}
}
RtlpCreateUCREntry(v6, p_Segment, (_HEAP_UCR_DESCRIPTOR *)BaseAddress - 1, RegionSize, v10, (UINT64 *)v51);
FreeSize = v51[0];
goto LABEL_30;
}
RtlpUpdateHeapRates(v6, 3ui64);
v25 = v54 == 0;
LABEL_33:
if( !v25 )
{
RtlpCreateUCREntry(v24, p_Segment, (_HEAP_UCR_DESCRIPTOR *)(v48 - 48), Size, v10, &FreeSizea);
v12 = FreeSizea;
}
goto LABEL_29;
}
BaseAddress = v10;
for( i = p_Segment->UCRSegmentList.Flink; &p_Segment->UCRSegmentList != i; i = i->Flink )
{
v17 = i - 1;
v18 = (_HEAP_FREE_ENTRY *)((char *)i[1].Flink + (unsigned __int64)i[1].Blink);
UCRBlock = (_HEAP_UCR_DESCRIPTOR *)&i[-1];
if( v18 == v10 )
goto LABEL_19;
}
v17 = 0i64;
UCRBlock = 0i64;
LABEL_19:
if( RtlpHeapErrorHandlerThreshold >= 1 && !v17 )
{
DbgPrint("(UCRBlock != NULL)");
RtlpHeapHandleError(v19);
}
v20 = 16 * v12;
if( v7 )
{
v21 = (__int64)v10 + v20;
v51[0] = (__int64)v10 + v20;
}
else
{
v51[0] = (__int64)v10 + v20;
v21 = (__int64)&v10[-1] + v20;
}
RegionSize = (v21 & 0xFFFFFFFFFFFFF000ui64) - (_QWORD)v10;
if( !RegionSize )
{
if( RtlpHeapErrorHandlerThreshold >= 1 )
{
if( v7 )
{
DbgPrint("(!TrailingUCR)");
RtlpHeapHandleError(v22);
}
}
goto LABEL_29;
}
if( ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x4000ui64) < 0 )
{
RtlpUpdateHeapRates(v6, 3ui64);
v25 = v7 == 0;
goto LABEL_33;
}
v26 = UCRBlock;
++v6->Counters.DeCommitOps;
v27 = v26->Size;
if( v27 >= 0xFF000 )
v6->Counters.TotalMemoryLargeUCR -= v27;
RtlpRemoveUCRBlock(v23);
v26->Size += RegionSize;
RtlpInsertUCRBlock(v6, v26);
p_Segment->NumberOfUnCommittedPages += RegionSize >> 12;
v28 = RegionSize;
v6->Counters.TotalMemoryCommitted -= RegionSize;
v29 = v26->Size;
if( v29 >= 0xFF000 )
v6->Counters.TotalMemoryLargeUCR += v29;
if( !v7 )
{
v30 = (char *)BaseAddress + v28;
*(_WORD *)((char *)BaseAddress + v28 + 12) = v6->Encoding.UnpackedEntry.PreviousSize;
if( (VOID *)v51[0] != (char *)BaseAddress + RegionSize )
{
v30[15] = 0;
v30[10] = 0;
v31 = (v20 - RegionSize) >> 4;
v32 = RtlpHeapErrorHandlerThreshold < 1;
*((_WORD *)v30 + 4) = v31;
if( !v32 && (unsigned __int16)v31 <= 1u )
{
DbgPrint("((LONG)FreeEntry->Size > 1)");
RtlpHeapHandleError(v33);
}
v30[11] = 0;
v34 = p_Segment->Heap;
if( v34 != (_HEAP *)p_Segment )
{
if( ((unsigned __int64)(v30 - (char *)p_Segment) >> 16) + 1 >= 0xFE )
{
RtlpLogHeapFailure(heap_failure_entry_corruption, v34, v30, p_Segment, 0i64);
LOWORD(v31) = *((_WORD *)v30 + 4);
}
v4 = ((unsigned int)((_DWORD)v30 - (_DWORD)p_Segment) >> 16) + 1;
}
v30[14] = v4;
FreeBlock = (_HEAP_FREE_ENTRY *)v30;
FreeSize = (unsigned __int16)v31;
goto LABEL_79;
}
if( v6->EncodeFlagMask )
{
v30[11] = v30[8] ^ v30[9] ^ v30[10];
*((_DWORD *)v30 + 2) ^= v6->Encoding.UnpackedEntry.SubSegmentCode;
}
}
}Referenced by:
RtlpFreeHeap