RtlpCreateSplitBlock

UINT8 __stdcall RtlpCreateSplitBlock(
        _HEAP *Heap,
        _HEAP_SEGMENT *Segment,
        _HEAP_FREE_ENTRY *SplitBlock,
        UINT8 FreeFlags,
        UINT8 PatternCheck,
        UINT16 PreviousBlockSize,
        UINT64 FreeSize){
  int v7; 
  _HEAP *v10; 
  unsigned __int64 v11; 
  __int16 v13; 
  char *v14; 
  VOID **v15; 
  _QWORD *v16; 
  char *v17; 
  VOID *v18; 
  _HEAP_LIST_LOOKUP *BlocksIndex; 
  _LIST_ENTRY *v20; 
  unsigned __int64 i; 
  _HEAP_LIST_LOOKUP *ExtendedLookup; 
  int v23; 
  char v24; 
  unsigned __int64 v25; 
  __int64 v26; 
  UINT64 v27; 
  _LIST_ENTRY *v28; 
  _LIST_ENTRY *Flink; 
  unsigned int v30; 
  int v31; 
  unsigned __int16 v32; 
  _LIST_ENTRY *v33; 
  _LIST_ENTRY *p_FreeList; 
  _HEAP_LIST_LOOKUP *v35; 
  _LIST_ENTRY *Size; 
  unsigned __int64 k; 
  _HEAP_LIST_LOOKUP *v38; 
  _LIST_ENTRY *v39; 
  _HEAP_FREE_ENTRY *v40; 
  unsigned __int64 v41; 
  _LIST_ENTRY *p_FreeLists; 
  _LIST_ENTRY *Entry; 
  unsigned int EncodeFlagMask; 
  int Blink; 
  unsigned __int16 v46; 
  _LIST_ENTRY *v47; 
  unsigned __int64 j; 
  _HEAP_LIST_LOOKUP *v49; 
  _LIST_ENTRY *v51; 
  _LIST_ENTRY *v52; 
  unsigned int v53; 
  int v54; 
  unsigned __int16 v55; 
  _LIST_ENTRY *v56; 
  unsigned __int64 m; 
  _HEAP_LIST_LOOKUP *v58; 
  _HEAP_FREE_ENTRY *v59; 
  unsigned __int64 v60; 
  _LIST_ENTRY *v61; 
  _LIST_ENTRY *v62; 
  unsigned int v63; 
  int v64; 
  unsigned __int16 v65; 
  _LIST_ENTRY *v66; 
  _LIST_ENTRY *v67; 
  _HEAP_LIST_LOOKUP *v68; 
  unsigned __int64 n; 
  _HEAP_LIST_LOOKUP *v70; 
  _LIST_ENTRY *v71; 
  VOID *Param2; 
  unsigned int v73; 
  unsigned int v74; 
  unsigned int v75; 
  unsigned int v76; 
  UINT64 FreeSizea; 

  v7 = 0;
  SplitBlock->HeapEntry.UnpackedEntry.UnusedBytes = 0;
  SplitBlock->HeapEntry.UnpackedEntry.Flags = FreeFlags;
  SplitBlock->HeapEntry.UnpackedEntry.PreviousSize = Heap->Encoding.UnpackedEntry.PreviousSize ^ PreviousBlockSize;
  v10 = Segment->Heap;
  if( v10 == (_HEAP *)Segment )
  {
    LOBYTE(v11) = 0;
  }
  else
  {
    v11 = ((unsigned __int64)((char *)SplitBlock - (char *)Segment) >> 16) + 1;
    if( v11 >= 0xFE )
      RtlpLogHeapFailure(heap_failure_entry_corruption, v10, SplitBlock, Segment, 0i64);
  }
  SplitBlock->HeapEntry.UnpackedEntry.SegmentOffset = v11;
  v13 = FreeSize;
  v14 = &SplitBlock->HeapEntry.gap0[16 * FreeSize];
  SplitBlock->HeapEntry.UnpackedEntry.SmallTagIndex = 0;
  SplitBlock->HeapEntry.UnpackedEntry.Size = FreeSize;
  while( (((unsigned __int8)v14[10] ^ Heap->Encoding.UnpackedEntry.Flags & (Heap->EncodeFlagMask >> 20)) & 1) == 0 )
  {
    if( Heap->EncodeFlagMask )
    {
      *((_DWORD *)v14 + 2) ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
      if( v14[11] != ((unsigned __int8)v14[8] ^ (unsigned __int8)(v14[9] ^ v14[10])) )
        RtlpAnalyzeHeapFailure(Heap, &SplitBlock->HeapEntry + FreeSize);
    }
    v15 = (VOID **)*((_QWORD *)v14 + 3);
    v16 = (_QWORD *)*((_QWORD *)v14 + 2);
    FreeSizea = (UINT64)v15;
    v17 = (char *)*v15;
    v18 = (VOID *)v16[1];
    if( *v15 == v18 && v17 == v14 + 16 )
    {
      Heap->TotalFreeSize -= *((unsigned __int16 *)v14 + 4);
      BlocksIndex = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
      if( BlocksIndex )
      {
        v20 = (_LIST_ENTRY *)*((unsigned __int16 *)v14 + 4);
        for( i = BlocksIndex->ArraySize; ; i = ExtendedLookup->ArraySize )
        {
          if( (unsigned __int64)v20 < i )
          {
            v23 = *((unsigned __int16 *)v14 + 4);
            goto LABEL_20;
          }
          ExtendedLookup = BlocksIndex->ExtendedLookup;
          if( !BlocksIndex->ExtendedLookup )
            break;
          BlocksIndex = BlocksIndex->ExtendedLookup;
        }
        v23 = BlocksIndex->ArraySize - 1;
LABEL_20:
        LODWORD(Param2) = v23;
        RtlpHeapRemoveListEntry(Heap, BlocksIndex, v20, (UINT64)(v14 + 16), (UINT64)Param2);
        v15 = (VOID **)FreeSizea;
      }
      *v15 = v16;
      v16[1] = v15;
      if( PatternCheck )
      {
        v24 = v14[10];
        if( (v24 & 4) != 0 )
        {
          v25 = 16i64 * *((unsigned __int16 *)v14 + 4) - 32;
          if( (v24 & 2) != 0 && v25 > 4 )
            v25 = 16i64 * *((unsigned __int16 *)v14 + 4) - 36;
          LODWORD(v26) = RtlCompareMemoryUlong(v14 + 32, v25, 0xFEEEFEEEui64);
          if( v26 != v25 )
          {
            DbgPrint(
              "HEAP: Free Heap block %p modified at %p after it was freed\n",
              &SplitBlock->HeapEntry.UnpackedEntry + FreeSize,
              &v14[v26 + 32]);
            if( (_BYTE)KdDebuggerEnabled )
              __debugbreak();
          }
        }
      }
      SplitBlock->HeapEntry.UnpackedEntry.Flags = v14[10];
      v27 = *((unsigned __int16 *)v14 + 4) + FreeSize;
      if( v27 > 0xFF00 )
      {
        RtlpInsertFreeBlock(Heap, SplitBlock, v27);
        return 1;
      }
      SplitBlock->HeapEntry.UnpackedEntry.Size = v27;
      *(&SplitBlock->HeapEntry.UnpackedEntry.PreviousSize + 8 * v27) = Heap->Encoding.UnpackedEntry.PreviousSize ^ v27;
      SplitBlock->HeapEntry.UnpackedEntry.UnusedBytes = 0;
      if( PatternCheck )
      {
        SplitBlock->HeapEntry.UnpackedEntry.Flags &= 0xF0u;
        if( (Heap->Flags & 0x40) != 0 )
        {
          v40 = SplitBlock + 1;
          v41 = (16 * (unsigned __int64)(unsigned __int16)v27 - 32) >> 2;
          if( v41 )
          {
            if( ((unsigned __int8)v40 & 4) != 0 )
            {
              --v41;
              LODWORD(v40->HeapEntry.UnpackedEntry.PreviousBlockPrivateData) = -17891602;
              v40 = (_HEAP_FREE_ENTRY *)((char *)SplitBlock + 36);
            }
            memset64(v40, 0xFEEEFEEEFEEEFEEEui64, v41 >> 1);
            if( (v41 & 1) != 0 )
              *((_DWORD *)&v40->HeapEntry.UnpackedEntry + v41 - 1) = -17891602;
          }
          SplitBlock->HeapEntry.UnpackedEntry.Flags |= 4u;
        }
        p_FreeLists = &Heap->FreeLists;
        if( Heap->BlocksIndex )
          Entry = RtlpFindEntry(Heap, (unsigned __int16)v27);
        else
          Entry = p_FreeLists->Flink;
        if( p_FreeLists != Entry )
        {
          EncodeFlagMask = Heap->EncodeFlagMask;
          do
          {
            if( EncodeFlagMask )
            {
              Blink = (int)Entry[-1].Blink;
              EncodeFlagMask = Heap->EncodeFlagMask;
              LOWORD(v74) = Blink;
              if( (Blink & EncodeFlagMask) != 0 )
                v74 = Heap->Encoding.UnpackedEntry.SubSegmentCode ^ Blink;
              v46 = v74;
            }
            else
            {
              v46 = (unsigned __int16)Entry[-1].Blink;
            }
            if( (unsigned __int16)v27 <= (unsigned __int64)v46 )
              break;
            Entry = Entry->Flink;
          }
          while( p_FreeLists != Entry );
        }
        v47 = Entry->Blink;
        p_FreeList = &SplitBlock->FreeList;
        if( v47->Flink == Entry )
        {
          p_FreeList->Flink = Entry;
          SplitBlock->FreeList.Blink = v47;
          v47->Flink = p_FreeList;
          Entry->Blink = p_FreeList;
        }
        else
        {
          RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, Entry, 0i64, v47->Flink);
        }
        Heap->TotalFreeSize += SplitBlock->HeapEntry.UnpackedEntry.Size;
        v35 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
        if( v35 )
        {
          Size = (_LIST_ENTRY *)SplitBlock->HeapEntry.UnpackedEntry.Size;
          for( j = v35->ArraySize; (unsigned __int64)Size >= j; j = v49->ArraySize )
          {
            v49 = v35->ExtendedLookup;
            if( !v35->ExtendedLookup )
              goto LABEL_84;
            v35 = v35->ExtendedLookup;
          }
          goto LABEL_52;
        }
      }
      else
      {
        SplitBlock->HeapEntry.UnpackedEntry.Flags = 0;
        v28 = &Heap->FreeLists;
        if( Heap->BlocksIndex )
          Flink = RtlpFindEntry(Heap, (unsigned __int16)v27);
        else
          Flink = v28->Flink;
        if( v28 != Flink )
        {
          v30 = Heap->EncodeFlagMask;
          do
          {
            if( v30 )
            {
              v31 = (int)Flink[-1].Blink;
              v30 = Heap->EncodeFlagMask;
              LOWORD(v73) = v31;
              if( (v31 & v30) != 0 )
                v73 = Heap->Encoding.UnpackedEntry.SubSegmentCode ^ v31;
              v32 = v73;
            }
            else
            {
              v32 = (unsigned __int16)Flink[-1].Blink;
            }
            if( (unsigned __int16)v27 <= (unsigned __int64)v32 )
              break;
            Flink = Flink->Flink;
          }
          while( v28 != Flink );
        }
        v33 = Flink->Blink;
        p_FreeList = &SplitBlock->FreeList;
        if( v33->Flink == Flink )
        {
          p_FreeList->Flink = Flink;
          SplitBlock->FreeList.Blink = v33;
          v33->Flink = p_FreeList;
          Flink->Blink = p_FreeList;
        }
        else
        {
          RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, Flink, 0i64, v33->Flink);
        }
        Heap->TotalFreeSize += SplitBlock->HeapEntry.UnpackedEntry.Size;
        v35 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
        if( v35 )
        {
          Size = (_LIST_ENTRY *)SplitBlock->HeapEntry.UnpackedEntry.Size;
          for( k = v35->ArraySize; (unsigned __int64)Size >= k; k = v38->ArraySize )
          {
            v38 = v35->ExtendedLookup;
            if( !v35->ExtendedLookup )
              goto LABEL_84;
            v35 = v35->ExtendedLookup;
          }
          goto LABEL_52;
        }
      }
      goto LABEL_54;
    }
    RtlpLogHeapFailure(heap_failure_freelists_corruption, Heap, v14 + 16, v18, v17);
    if( v7 )
      return 0;
    v7 = 1;
  }
  *((_WORD *)v14 + 6) = Heap->Encoding.UnpackedEntry.PreviousSize ^ v13;
  SplitBlock->HeapEntry.UnpackedEntry.UnusedBytes = 0;
  if( !PatternCheck )
  {
    SplitBlock->HeapEntry.UnpackedEntry.Flags = 0;
    v51 = &Heap->FreeLists;
    if( Heap->BlocksIndex )
      v52 = RtlpFindEntry(Heap, (unsigned __int16)FreeSize);
    else
      v52 = v51->Flink;
    if( v51 != v52 )
    {
      v53 = Heap->EncodeFlagMask;
      do
      {
        if( v53 )
        {
          v54 = (int)v52[-1].Blink;
          v53 = Heap->EncodeFlagMask;
          LOWORD(v75) = v54;
          if( (v53 & v54) != 0 )
            v75 = Heap->Encoding.UnpackedEntry.SubSegmentCode ^ v54;
          v55 = v75;
        }
        else
        {
          v55 = (unsigned __int16)v52[-1].Blink;
        }
        if( (unsigned __int16)FreeSize <= (unsigned __int64)v55 )
          break;
        v52 = v52->Flink;
      }
      while( v51 != v52 );
    }
    v56 = v52->Blink;
    p_FreeList = &SplitBlock->FreeList;
    if( v56->Flink == v52 )
    {
      p_FreeList->Flink = v52;
      SplitBlock->FreeList.Blink = v56;
      v56->Flink = p_FreeList;
      v52->Blink = p_FreeList;
    }
    else
    {
      RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, v52, 0i64, v56->Flink);
    }
    Heap->TotalFreeSize += SplitBlock->HeapEntry.UnpackedEntry.Size;
    v35 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
    if( v35 )
    {
      Size = (_LIST_ENTRY *)SplitBlock->HeapEntry.UnpackedEntry.Size;
      for( m = v35->ArraySize; (unsigned __int64)Size >= m; m = v58->ArraySize )
      {
        v58 = v35->ExtendedLookup;
        if( !v35->ExtendedLookup )
        {
LABEL_84:
          v39 = (_LIST_ENTRY *)(v35->ArraySize - 1);
          goto LABEL_53;
        }
        v35 = v35->ExtendedLookup;
      }
LABEL_52:
      v39 = Size;
LABEL_53:
      LODWORD(Param2) = (_DWORD)v39;
      RtlpHeapAddListEntry(Heap, v35, v39, (UINT64)p_FreeList, (UINT64)Param2);
    }
LABEL_54:
    if( Heap->EncodeFlagMask )
    {
      SplitBlock->HeapEntry.UnpackedEntry.SmallTagIndex = LOBYTE(SplitBlock->InterceptorValue) ^ BYTE1(SplitBlock->Code1) ^ SplitBlock->HeapEntry.UnpackedEntry.Flags;
      SplitBlock->HeapEntry.UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
    }
    return 1;
  }
  SplitBlock->HeapEntry.UnpackedEntry.Flags &= 0xF0u;
  if( (Heap->Flags & 0x40) != 0 )
  {
    v59 = SplitBlock + 1;
    v60 = (16 * (unsigned __int64)(unsigned __int16)FreeSize - 32) >> 2;
    if( v60 )
    {
      if( ((unsigned __int8)v59 & 4) != 0 )
      {
        --v60;
        LODWORD(v59->HeapEntry.UnpackedEntry.PreviousBlockPrivateData) = -17891602;
        v59 = (_HEAP_FREE_ENTRY *)((char *)SplitBlock + 36);
      }
      memset64(v59, 0xFEEEFEEEFEEEFEEEui64, v60 >> 1);
      if( (v60 & 1) != 0 )
        *((_DWORD *)&v59->HeapEntry.UnpackedEntry + v60 - 1) = -17891602;
    }
    SplitBlock->HeapEntry.UnpackedEntry.Flags |= 4u;
  }
  v61 = &Heap->FreeLists;
  if( Heap->BlocksIndex )
    v62 = RtlpFindEntry(Heap, (unsigned __int16)FreeSize);
  else
    v62 = v61->Flink;
  if( v61 != v62 )
  {
    v63 = Heap->EncodeFlagMask;
    do
    {
      if( v63 )
      {
        v64 = (int)v62[-1].Blink;
        v63 = Heap->EncodeFlagMask;
        LOWORD(v76) = v64;
        if( (v63 & v64) != 0 )
          v76 = Heap->Encoding.UnpackedEntry.SubSegmentCode ^ v64;
        v65 = v76;
      }
      else
      {
        v65 = (unsigned __int16)v62[-1].Blink;
      }
      if( (unsigned __int16)FreeSize <= (unsigned __int64)v65 )
        break;
      v62 = v62->Flink;
    }
    while( v61 != v62 );
  }
  v66 = v62->Blink;
  v67 = &SplitBlock->FreeList;
  if( v66->Flink == v62 )
  {
    v67->Flink = v62;
    SplitBlock->FreeList.Blink = v66;
    v66->Flink = v67;
    v62->Blink = v67;
  }
  else
  {
    RtlpLogHeapFailure(heap_failure_freelists_corruption, 0i64, v62, 0i64, v66->Flink);
  }
  Heap->TotalFreeSize += SplitBlock->HeapEntry.UnpackedEntry.Size;
  v68 = (_HEAP_LIST_LOOKUP *)Heap->BlocksIndex;
  if( v68 )
  {
    for( n = v68->ArraySize; ; n = v70->ArraySize )
    {
      if( SplitBlock->HeapEntry.UnpackedEntry.Size < n )
      {
        v71 = (_LIST_ENTRY *)SplitBlock->HeapEntry.UnpackedEntry.Size;
        goto LABEL_137;
      }
      v70 = v68->ExtendedLookup;
      if( !v68->ExtendedLookup )
        break;
      v68 = v68->ExtendedLookup;
    }
    v71 = (_LIST_ENTRY *)(v68->ArraySize - 1);
LABEL_137:
    LODWORD(Param2) = (_DWORD)v71;
    RtlpHeapAddListEntry(Heap, v68, v71, (UINT64)&SplitBlock->FreeList, (UINT64)Param2);
  }
  if( Heap->EncodeFlagMask )
  {
    SplitBlock->HeapEntry.UnpackedEntry.SmallTagIndex = LOBYTE(SplitBlock->InterceptorValue) ^ BYTE1(SplitBlock->Code1) ^ SplitBlock->HeapEntry.UnpackedEntry.Flags;
    SplitBlock->HeapEntry.UnpackedEntry.SubSegmentCode ^= Heap->Encoding.UnpackedEntry.SubSegmentCode;
  }
  return 1;
}

Referenced by:

RtlpAllocateHeap