ExpSaPageGroupDescriptorAllocate

CHAR *__fastcall ExpSaPageGroupDescriptorAllocate(INT64 a1, CHAR a2){
  __int64 v4; 
  int v5; 
  CHAR *result; 
  __int64 v7; 
  CHAR *v8; 
  char v9; 
  int v10; 
  unsigned int v11; 
  __int64 v12; 
  struct _KPRCB *CurrentPrcb; 
  unsigned __int16 v14; 
  UINT64 v15; 
  void *PoolWithTagFromNode; 
  unsigned int v17; 
  _ETHREAD *v18; 
  char v19; 
  int v20; 
  bool v21; 
  __int64 v22; 
  unsigned __int64 v23; 
  __int64 v24; 
  unsigned __int8 v25; 
  __int64 v26; 
  int SessionId; 
  _ETHREAD *CurrentThread; 
  __int64 v29; 
  struct _GROUP_AFFINITY *p_PreviousAffinity; 
  UINT64 v31; 
  INT64 v32; 
  unsigned int v33; 
  unsigned int v34; 
  int v35; 
  __int64 v36; 
  ULONG_PTR BugCheckParameter4; 
  char v38; 
  unsigned int MaximumProcessorCount; 
  int v41; 
  int v42; 
  unsigned int v43; 
  unsigned int v44; 
  int v45; 
  _QWORD **v46; 
  struct _GROUP_AFFINITY Affinity; 
  struct _GROUP_AFFINITY PreviousAffinity; 
  v38 = 0;
  Affinity = 0i64;
  PreviousAffinity = 0i64;
  MaximumProcessorCount = KeQueryMaximumProcessorCountEx(0xFFFFu);
  LODWORD(v4) = 0;
  v5 = a2 != 0 ? 1 : 512;
  result = (CHAR *)ExAllocatePoolWithTag((_POOL_TYPE)v5, 0x80ui64, 0x61537845ui64);
  v7 = 0i64;
  v8 = result;
  if( !result )
    return result;
  memset((INT64)result, 0i64);
  *((_QWORD *)v8 + 6) = 512i64;
  *((_QWORD *)v8 + 7) = v8 + 64;
  *((_QWORD *)v8 + 2) = a1;
  *((_DWORD *)v8 + 9) = 512;
  v43 = 0;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  --*((_WORD *)CurrentThread + 243);
  if( ++*((_BYTE *)CurrentThread + 794) != 1 )
    KeBugCheckEx(
      0x192u,
      (ULONG_PTR)CurrentThread,
      (ULONG_PTR)&ExSaPageGroupDescriptorArrayLock,
      KeGetCurrentIrql(),
      0i64);
  v25 = *((_BYTE *)CurrentThread + 792);
  v17 = -1;
  v42 = 0;
  if( !v25 )
  {
    if( !*((_BYTE *)CurrentThread + 870) )
      goto LABEL_54;
    v29 = *((unsigned __int8 *)CurrentThread + 870);
    *((_BYTE *)CurrentThread + 870) = 0;
    v25 = *((_BYTE *)CurrentThread + 792) | v29;
  }
  _BitScanForward((unsigned int *)&v26, v25);
  v42 = v26;
  *((_BYTE *)CurrentThread + 792) = v25 & ~(1 << v26);
  v7 = *((_QWORD *)CurrentThread + 100) + 96 * v26;
  if( v7 )
  {
    if( (unsigned __int64)&ExSaPageGroupDescriptorArrayLock >= 0xFFFF800000000000ui64
      && *((_BYTE *)&antNameB + (((unsigned __int64)&ExSaPageGroupDescriptorArrayLock >> 39) & 0x1FF) - 256) == 1 )
    {
      SessionId = MmGetSessionIdEx(*((_QWORD *)CurrentThread + 23));
    }
    else
    {
      SessionId = -1;
    }
    *(_DWORD *)(v7 + 40) = SessionId;
    *(_QWORD *)(v7 + 32) = (unsigned __int64)&ExSaPageGroupDescriptorArrayLock & 0x7FFFFFFFFFFFFFFCi64;
    goto LABEL_51;
  }
LABEL_54:
  _interlockedbittestandset((volatile signed __int32 *)CurrentThread + 30, 0x10u);
LABEL_51:
  --*((_BYTE *)CurrentThread + 794);
  KiAbThreadRemoveBoosts((ULONG_PTR)CurrentThread, (__int64)&ExSaPageGroupDescriptorArrayLock, &v43);
  v21 = (*((_WORD *)CurrentThread + 243))++ == 0xFFFF;
  if( v21 && *((_ETHREAD **)CurrentThread + 19) != (_ETHREAD *)((char *)CurrentThread + 152) )
    KiCheckForKernelApcDelivery();
  if( _interlockedbittestandset64((volatile signed __int32 *)&ExSaPageGroupDescriptorArrayLock, 0i64) )
    ExfAcquirePushLockExclusiveEx(&ExSaPageGroupDescriptorArrayLock, (VOID *)v7, &ExSaPageGroupDescriptorArrayLock);
  v9 = 1;
  if( v7 )
    *(_BYTE *)(v7 + 26) |= 1u;
  v10 = ExpSaBinaryArrayInsert(
          (_QWORD **)ExSaPageGroupDescriptorArray,
          (__int64)v8,
          *(_WORD *)(*((_QWORD *)KeGetCurrentPrcb() + 24) + 146i64));
  *((_DWORD *)v8 + 8) = v10;
  if( v10 == -1 )
    goto LABEL_68;
  v11 = KeNumberProcessors_0;
  v44 = KeNumberProcessors_0;
  if( !MaximumProcessorCount )
  {
LABEL_17:
    PoolWithTagFromNode = 0i64;
    goto LABEL_18;
  }
  v12 = 0i64;
  while( 1 )
  {
    v46 = *(_QWORD ***)(v12 + ExSaPageArrays);
    if( (unsigned int)v4 >= v11 )
      CurrentPrcb = KeGetCurrentPrcb();
    else
      KeGetPrcb((unsigned int)v4);
    v14 = *(_WORD *)(*((_QWORD *)CurrentPrcb + 24) + 146i64);
    if( a2 )
      break;
    LODWORD(BugCheckParameter4) = 0;
    v15 = v14;
    LODWORD(v15) = v14 | 0x80000000;
    PoolWithTagFromNode = ExpAllocatePoolWithTagFromNode(
                            (unsigned int)v5,
                            0x1000ui64,
                            0x61537845ui64,
                            v15,
                            BugCheckParameter4);
    if( !PoolWithTagFromNode )
      goto LABEL_67;
LABEL_14:
    if( (unsigned int)ExpSaBinaryArrayInsert(v46, (__int64)PoolWithTagFromNode, v14) == -1 )
      goto LABEL_67;
    v9 = 1;
    v12 += 8i64;
    LODWORD(v4) = v4 + 1;
    if( (unsigned int)v4 >= MaximumProcessorCount )
      goto LABEL_17;
    v11 = v44;
  }
  KeQueryNodeActiveAffinity(v14, &Affinity, 0i64);
  if( v38 )
  {
    p_PreviousAffinity = 0i64;
  }
  else
  {
    v38 = 1;
    p_PreviousAffinity = &PreviousAffinity;
  }
  KeSetSystemGroupAffinityThread(&Affinity, p_PreviousAffinity);
  PoolWithTagFromNode = ExAllocatePoolWithTag((_POOL_TYPE)v5, 0x1000ui64, 0x61537845ui64);
  if( PoolWithTagFromNode )
    goto LABEL_14;
LABEL_67:
  v9 = 0;
LABEL_18:
  if( v38 )
    KeRevertToUserGroupAffinityThread(&PreviousAffinity);
  if( PoolWithTagFromNode )
    ExFreeHeapPool(PoolWithTagFromNode);
  v17 = -1;
  if( !v9 )
  {
LABEL_68:
    v31 = *((unsigned int *)v8 + 8);
    if( (_DWORD)v31 != -1 )
    {
      if( (_DWORD)v4 )
      {
        do
        {
          v4 = (unsigned int)(v4 - 1);
          v32 = *(_QWORD *)(ExSaPageArrays + 8 * v4);
          v33 = *((_DWORD *)v8 + 8);
          _BitScanReverse(&v34, v33);
          v35 = 1 << v34;
          v36 = v34 - 2;
          v45 = v36;
          ExFreeHeapPool(*(PVOID *)(*(_QWORD *)(v32 + 8 * v36) + 8i64 * (v33 ^ v35) + 8));
          ExpSaBinaryArrayRemove(v32, *((unsigned int *)v8 + 8));
        }
        while( (_DWORD)v4 );
        v31 = *((unsigned int *)v8 + 8);
      }
      ExpSaBinaryArrayRemove(ExSaPageGroupDescriptorArray, v31);
    }
    ExFreeHeapPool(v8);
    v8 = 0i64;
  }
  if( (_InterlockedExchangeAdd64((volatile signed __int64 *)&ExSaPageGroupDescriptorArrayLock, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock((volatile INT64 *)&ExSaPageGroupDescriptorArrayLock);
  v41 = 0;
  v18 = (_ETHREAD *)KeGetCurrentThread();
  if( (unsigned int)MiGetSystemRegionType((UINT64)&ExSaPageGroupDescriptorArrayLock) == 1 )
    v17 = MmGetSessionIdEx(*((_QWORD *)v18 + 23));
  --*((_WORD *)v18 + 243);
  v19 = ++*((_BYTE *)v18 + 794);
  v20 = (*((char *)v18 + 792) | *((char *)v18 + 870)) ^ 0x3F;
  while( 1 )
  {
    v21 = !_BitScanReverse((unsigned int *)&v22, v20);
    if( v21 )
      break;
    v23 = *((_QWORD *)v18 + 100) + 96 * v22;
    v20 &= ~(1 << v22);
    if( (*(_BYTE *)(v23 + 26) & 1) != 0
      && (*(_DWORD *)(v23 + 32) & 1) == 0
      && (*(_QWORD *)(v23 + 32) & 0x7FFFFFFFFFFFFFFCi64) == ((unsigned __int64)&ExSaPageGroupDescriptorArrayLock & 0x7FFFFFFFFFFFFFFCi64)
      && *(_DWORD *)(v23 + 40) == v17 )
    {
      *(_BYTE *)(v23 + 26) &= ~1u;
      if( *(_QWORD *)(v23 + 32) )
      {
        if( v23 )
        {
          *(_BYTE *)(v23 + 32) |= 2u;
          if( *(__int64 *)(v23 + 32) < 0 )
            KiAbEntryRemoveFromTree(v23);
          v41 = *(_DWORD *)(v23 + 88) & 0x1FFFF;
          *(_DWORD *)(v23 + 88) &= 0xFFFE0000;
          *(_BYTE *)(v23 + 25) &= ~1u;
          *(_QWORD *)(v23 + 32) = 0i64;
          v24 = (__int64)(v23 - *((_QWORD *)v18 + 100)) / 96;
          if( v19 == 1 )
            *((_BYTE *)v18 + 792) |= 1 << v24;
          else
            _InterlockedOr8((volatile signed __int8 *)v18 + 870, 1 << v24);
          goto LABEL_39;
        }
        break;
      }
    }
  }
  if( (*((_DWORD *)v18 + 30) & 0x10000) == 0 )
    KeBugCheckEx(0x162u, (ULONG_PTR)v18, (ULONG_PTR)&ExSaPageGroupDescriptorArrayLock, v17, 0i64);
LABEL_39:
  --*((_BYTE *)v18 + 794);
  KiAbThreadRemoveBoosts((ULONG_PTR)v18, (__int64)&ExSaPageGroupDescriptorArrayLock, (unsigned int *)&v41);
  v21 = (*((_WORD *)v18 + 243))++ == 0xFFFF;
  if( v21 && *((_ETHREAD **)v18 + 19) != (_ETHREAD *)((char *)v18 + 152) )
    KiCheckForKernelApcDelivery();
  return v8;
}

Referenced by:

ExpSaAllocatorAllocate