RtlpFreeHeap

UINT64 __stdcall RtlpFreeHeap(_HEAP *Heap, UINT64 Flags, _HEAP_ENTRY *BusyBlock, VOID *BaseAddress){
  char v6; 
  int v8; 
  int v9; 
  void **BlocksIndex; 
  unsigned __int8 v11; 
  _HEAP_FREE_ENTRY *v12; 
  unsigned __int16 v13; 
  bool v14; 
  UINT64 v15; 
  _LIST_ENTRY *p_FreeLists; 
  _LIST_ENTRY *Entry; 
  unsigned int Blink; 
  unsigned __int16 v19; 
  _LIST_ENTRY *p_FreeList; 
  VOID **p_Flink; 
  _HEAP_LIST_LOOKUP *v22; 
  _LIST_ENTRY *ArraySize; 
  int Size; 
  _HEAP_FREE_ENTRY *v25; 
  unsigned __int64 v26; 
  _LIST_ENTRY *v27; 
  _LIST_ENTRY *Flink; 
  unsigned int v29; 
  unsigned __int16 v30; 
  VOID **v31; 
  _HEAP_ENTRY *v32; 
  void *PreviousBlockPrivateData; 
  _QWORD *v34; 
  VOID **CompactHeader; 
  _HEAP_ENTRY *v36; 
  VOID *v37; 
  UINT64 *Param2; 
  VOID *Param2a; 
  VOID *v40; 
  char v41; 
  VOID *BaseAddressa; 
  _HEAP_FREE_ENTRY *v43; 
  unsigned int v44; 
  unsigned int v45; 
  _HEAP_FREE_ENTRY *v46; 
  UINT64 FreeSize; 

  FreeSize = 0i64;
  v6 = 0;
  v41 = 0;
  BaseAddressa = 0i64;
  if( Heap == (_HEAP *)BusyBlock )
  {
    RtlpLogHeapFailure(heap_failure_invalid_argument, Heap, BusyBlock, 0i64, 0i64);
    return 0i64;
  }
  v8 = Heap->ForceFlags | Flags;
  v9 = v8 & 0x3C010F60;
  if( (v8 & 1) != 0 )
  {
    if( Heap->EncodeFlagMask )
    {
      BusyBlock->UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
      if( BusyBlock->UnpackedEntry.SmallTagIndex != (LOBYTE(BusyBlock->Code1) ^ (unsigned __int8)(BYTE1(BusyBlock->AgregateCode) ^ BusyBlock->UnpackedEntry.Flags)) )
        RtlpAnalyzeHeapFailure(Heap, BusyBlock);
    }
  }
  else
  {
    ExAcquireResourceExclusiveLite((UINT64)Heap->LockVariable, 1, (INT64)BusyBlock);
    v6 = 1;
    v41 = 1;
    if( Heap->EncodeFlagMask )
    {
      BusyBlock->UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
      if( BusyBlock->UnpackedEntry.SmallTagIndex != (LOBYTE(BusyBlock->Code1) ^ (unsigned __int8)(BYTE1(BusyBlock->AgregateCode) ^ BusyBlock->UnpackedEntry.Flags)) )
        RtlpAnalyzeHeapFailure(Heap, BusyBlock);
    }
    BlocksIndex = (void **)Heap->BlocksIndex;
    do
    {
      if( BusyBlock->UnpackedEntry.Size < (unsigned __int64)*((unsigned int *)BlocksIndex + 2) )
        break;
      BlocksIndex = (void **)*BlocksIndex;
    }
    while( BlocksIndex );
  }
  v11 = BusyBlock->UnpackedEntry.Flags;
  if( (v11 & 8) != 0 )
    BusyBlock->UnpackedEntry.Flags = v11 & 0xF7;
  if( BusyBlock->UnpackedEntry.UnusedBytes == 4 )
  {
    v32 = BusyBlock - 3;
    PreviousBlockPrivateData = BusyBlock[-1].UnpackedEntry.PreviousBlockPrivateData;
    BaseAddressa = (VOID *)((unsigned __int64)&BusyBlock[-3] & 0xFFFFFFFFFFFF0000ui64);
    Heap->Counters.TotalSizeInVirtualBlocks -= (unsigned __int64)PreviousBlockPrivateData;
    v34 = BusyBlock[-3].UnpackedEntry.PreviousBlockPrivateData;
    CompactHeader = (VOID **)BusyBlock[-3].UnpackedEntry.CompactHeader;
    v36 = (_HEAP_ENTRY *)*CompactHeader;
    v37 = (VOID *)v34[1];
    if( *CompactHeader == v37 && v36 == v32 )
    {
      *CompactHeader = v34;
      v34[1] = CompactHeader;
    }
    else
    {
      RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, v32, v37, v36);
    }
    if( v6 )
    {
      ExReleaseResourceLite((PERESOURCE)Heap->LockVariable);
      v6 = 0;
    }
    FreeSize = 0i64;
    ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &BaseAddressa, &FreeSize, 0x8000ui64);
    goto LABEL_82;
  }
  FreeSize = BusyBlock->UnpackedEntry.Size;
  v12 = RtlpCoalesceFreeBlocks(Heap, (_HEAP_FREE_ENTRY *)BusyBlock, &FreeSize, (UINT64 *)BaseAddress, Param2, v40);
  v46 = v12;
  v13 = FreeSize;
  if( FreeSize < Heap->DeCommitFreeBlockThreshold || FreeSize + Heap->TotalFreeSize < Heap->DeCommitTotalFreeThreshold )
  {
    if( FreeSize > 0xFF00 )
    {
      RtlpInsertFreeBlock(Heap, v12, FreeSize);
      goto LABEL_82;
    }
    v14 = v9 == 0;
    v15 = (unsigned __int16)FreeSize;
    if( v14 )
    {
      v12->HeapEntry.UnpackedEntry.Flags = 0;
      v12->HeapEntry.UnpackedEntry.UnusedBytes = 0;
      p_FreeLists = &Heap->FreeLists;
      if( Heap->BlocksIndex )
        Entry = RtlpFindEntry(Heap, v13);
      else
        Entry = p_FreeLists->Flink;
      while( p_FreeLists != Entry )
      {
        if( Heap->EncodeFlagMask )
        {
          Blink = (unsigned int)Entry[-1].Blink;
          v44 = Blink;
          if( (Blink & Heap->EncodeFlagMask) != 0 )
            v44 = Blink ^ Heap->Encoding.UnpackedEntry.SubSegmentCode;
          v19 = v44;
          v12 = v46;
          v6 = v41;
        }
        else
        {
          v19 = (unsigned __int16)Entry[-1].Blink;
        }
        if( v15 <= v19 )
          break;
        Entry = Entry->Flink;
      }
      p_FreeList = &v12->FreeList;
      p_Flink = (VOID **)&Entry->Blink->Flink;
      if( *p_Flink == Entry )
      {
        p_FreeList->Flink = Entry;
        v12->FreeList.Blink = (_LIST_ENTRY *)p_Flink;
        *p_Flink = p_FreeList;
        Entry->Blink = p_FreeList;
      }
      else
      {
        RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, Entry, 0i64, *p_Flink);
      }
      Heap->TotalFreeSize += v12->HeapEntry.UnpackedEntry.Size;
      v22 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
      if( !v22 )
        goto LABEL_70;
      while( 1 )
      {
        ArraySize = (_LIST_ENTRY *)v22->ArraySize;
        if( v12->HeapEntry.UnpackedEntry.Size < (unsigned __int64)ArraySize )
        {
          Size = v12->HeapEntry.UnpackedEntry.Size;
          goto LABEL_69;
        }
        if( !v22->ExtendedLookup )
          break;
        v22 = v22->ExtendedLookup;
      }
      Size = (_DWORD)ArraySize - 1;
LABEL_69:
      LODWORD(Param2a) = Size;
      RtlpHeapAddListEntry(Heap, v22, ArraySize, (UINT64)p_FreeList, (UINT64)Param2a);
LABEL_70:
      if( Heap->EncodeFlagMask )
      {
        v12->HeapEntry.UnpackedEntry.SmallTagIndex = LOBYTE(v12->InterceptorValue) ^ BYTE1(v12->Code1) ^ v12->HeapEntry.UnpackedEntry.Flags;
        v12->HeapEntry.UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
      }
      goto LABEL_82;
    }
    v12->HeapEntry.UnpackedEntry.Flags &= 0xF0u;
    v12->HeapEntry.UnpackedEntry.UnusedBytes = 0;
    if( (Heap->Flags & 0x40) == 0 )
    {
LABEL_50:
      v27 = &Heap->FreeLists;
      if( Heap->BlocksIndex )
        Flink = RtlpFindEntry(Heap, v15);
      else
        Flink = v27->Flink;
      while( v27 != Flink )
      {
        if( Heap->EncodeFlagMask )
        {
          v29 = (unsigned int)Flink[-1].Blink;
          v45 = v29;
          if( (v29 & Heap->EncodeFlagMask) != 0 )
            v45 = v29 ^ Heap->Encoding.UnpackedEntry.SubSegmentCode;
          v30 = v45;
          v12 = v46;
          v6 = v41;
        }
        else
        {
          v30 = (unsigned __int16)Flink[-1].Blink;
        }
        if( v15 <= v30 )
          break;
        Flink = Flink->Flink;
      }
      p_FreeList = &v12->FreeList;
      v31 = (VOID **)&Flink->Blink->Flink;
      if( *v31 == Flink )
      {
        p_FreeList->Flink = Flink;
        v12->FreeList.Blink = (_LIST_ENTRY *)v31;
        *v31 = p_FreeList;
        Flink->Blink = p_FreeList;
      }
      else
      {
        RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, Flink, 0i64, *v31);
      }
      Heap->TotalFreeSize += v12->HeapEntry.UnpackedEntry.Size;
      v22 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
      if( !v22 )
        goto LABEL_70;
      while( 1 )
      {
        ArraySize = (_LIST_ENTRY *)v22->ArraySize;
        if( v12->HeapEntry.UnpackedEntry.Size < (unsigned __int64)ArraySize )
        {
          Size = v12->HeapEntry.UnpackedEntry.Size;
          goto LABEL_69;
        }
        if( !v22->ExtendedLookup )
          break;
        v22 = v22->ExtendedLookup;
      }
      Size = (_DWORD)ArraySize - 1;
      goto LABEL_69;
    }
    v25 = v12 + 1;
    v43 = v12 + 1;
    v26 = (16 * v15 - 32) >> 2;
    if( v26 )
    {
      if( ((unsigned __int8)v25 & 4) == 0 )
        goto LABEL_47;
      LODWORD(v25->HeapEntry.UnpackedEntry.PreviousBlockPrivateData) = -17891602;
      if( --v26 )
      {
        v25 = (_HEAP_FREE_ENTRY *)((char *)v12 + 36);
        v43 = (_HEAP_FREE_ENTRY *)((char *)v12 + 36);
LABEL_47:
        memset64(v25, 0xFEEEFEEEFEEEFEEEui64, v26 >> 1);
        if( (v26 & 1) != 0 )
          *((_DWORD *)&v25->HeapEntry.UnpackedEntry + v26 - 1) = -17891602;
      }
    }
    v12->HeapEntry.UnpackedEntry.Flags |= 4u;
    goto LABEL_50;
  }
  RtlpDeCommitFreeBlock(Heap, v12, FreeSize);
LABEL_82:
  if( v6 )
    ExReleaseResourceLite((PERESOURCE)Heap->LockVariable);
  return 1i64;
}

Referenced by:

RtlpFreeHeapInternal