ObWaitForMultipleObjects

NTSTATUS __stdcall ObWaitForMultipleObjects(
        UINT64 Count,
        VOID **CapturedHandles,
        INT8 AccessMode,
        _WAIT_TYPE WaitType,
        INT8 WaitMode,
        UINT8 Alertable,
        _LARGE_INTEGER *Timeout){
  VOID **v7; 
  __int64 v8; 
  int v9; 
  _ETHREAD *CurrentThread; 
  _EPROCESS *Process; 
  char v12; 
  _HANDLE_TABLE *ObjectTable; 
  INT8 v14; 
  __int64 v15; 
  unsigned int v16; 
  unsigned __int64 v17; 
  _OBJECT_HEADER *v18; 
  _EXHANDLE v19; 
  _HANDLE_TABLE *v20; 
  _HANDLE_TABLE_ENTRY *v21; 
  _HANDLE_TABLE_ENTRY *v22; 
  __int64 LowValue; 
  __int64 v24; 
  _HANDLE_TABLE_ENTRY v25; 
  unsigned __int8 v26; 
  _OBJECT_HEADER *v27; 
  __int32 v28; 
  _QUAD *p_Body; 
  unsigned __int64 v30; 
  _WAIT_TYPE v31; 
  __int64 v32; 
  __int64 v33; 
  unsigned int v34; 
  bool v35; 
  VOID *v36; 
  NTSTATUS v37; 
  _EX_RUNDOWN_REF *v38; 
  VOID **v39; 
  unsigned __int64 v41; 
  void *PoolWithTag; 
  _OBJECT_HEADER *v43; 
  NTSTATUS v44; 
  VOID **v45; 
  unsigned int v46; 
  unsigned int v47; 
  VOID *v48; 
  __int64 v49; 
  VOID *v50; 
  char *v51; 
  NTSTATUS v52; 
  __int64 v53; 
  void *v54; 
  unsigned int v55; 
  PVOID *v56; 
  __int64 v57; 
  int v58[8]; 
  INT8 v59; 
  char v60; 
  char v61; 
  INT8 v62; 
  PVOID P; 
  unsigned __int64 v64; 
  _EX_RUNDOWN_REF *v65; 
  _ETHREAD *Thread; 
  _HANDLE_TABLE_ENTRY HandleData; 
  _WAIT_TYPE WaitTypea; 
  unsigned int Counta; 
  NTSTATUS Count_4; 
  int v71; 
  _HANDLE_TABLE *v72; 
  _NPAGED_LOOKASIDE_LIST *Lookaside; 
  VOID **v74; 
  _LARGE_INTEGER *v75; 
  _EPROCESS *v76; 
  VOID *Object[64]; 
  __int64 v78[64]; 

  WaitTypea = WaitType;
  v59 = AccessMode;
  v7 = CapturedHandles;
  v74 = CapturedHandles;
  v8 = (unsigned int)Count;
  Counta = Count;
  v75 = Timeout;
  HandleData = 0i64;
  memset(v78, 0i64, sizeof(v78));
  v64 = 0i64;
  memset(Object, 0i64, sizeof(Object));
  v62 = 0;
  v61 = 0;
  P = 0i64;
  v9 = 0;
  Lookaside = 0i64;
  if( (unsigned int)v8 > 3 )
  {
    v41 = 48 * v8;
    if( (unsigned int)v8 > 0xA )
    {
      Lookaside = &ObpWaitBlockLookaside + ((int)v8 - 11) / 0xEu;
      PoolWithTag = ExAllocateFromNPagedLookasideList(Lookaside);
    }
    else
    {
      PoolWithTag = ExAllocatePoolWithTag(0x200ui64, 48 * v8, 1834443343i64);
    }
    P = PoolWithTag;
    if( PoolWithTag )
    {
      v61 = 1;
    }
    else
    {
      v62 = KeSetKernelStackSwapEnable(0);
      v53 = v41 + 15;
      if( v41 + 15 <= v41 )
        v53 = 0xFFFFFFFFFFFFFF0i64;
      v54 = alloca(v53 & 0xFFFFFFFFFFFFFFF0ui64);
      P = &v59;
    }
  }
  v60 = 0;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  Thread = CurrentThread;
  Process = CurrentThread->Tcb.ApcState.Process;
  v65 = (_EX_RUNDOWN_REF *)Process;
  v76 = Process;
  v12 = 1;
  --CurrentThread->Tcb.KernelApcDisable;
  if( Process == CurrentThread->Tcb.Process )
  {
    ObjectTable = Process->ObjectTable;
    v72 = ObjectTable;
LABEL_4:
    v14 = v59;
    goto LABEL_5;
  }
  ObjectTable = ObReferenceProcessHandleTable(Process);
  v72 = ObjectTable;
  if( ObjectTable )
  {
    v60 = 1;
    goto LABEL_4;
  }
  v55 = 0;
  if( !(_DWORD)v8 )
    goto LABEL_4;
  v56 = v7;
  v14 = v59;
  while( ObpIsKernelHandle(*v56, v14) )
  {
    ++v55;
    v56 = (PVOID *)(v57 + 8);
    if( v55 >= (unsigned int)v8 )
    {
      ObjectTable = v72;
LABEL_5:
      v15 = 0i64;
      v16 = 1;
      v17 = 0x140000000ui64;
      v18 = (_OBJECT_HEADER *)v64;
      while( 2 )
      {
        v19 = (_EXHANDLE)v7[v15];
        if( v14 || (v19.Value & 0xFFFFFFFF80000000ui64) != 0xFFFFFFFF80000000ui64 || v19.Value > 0xFFFFFFFFFFFFFFFDui64 )
        {
          v20 = ObjectTable;
        }
        else
        {
          v19 = (_EXHANDLE)(v19.Value ^ 0xFFFFFFFF80000000ui64);
          v20 = HandleTable;
        }
        if( (v19._bf_0 & 0x3FC) != 0 )
        {
          v21 = ExpLookupHandleTableEntry(v20, v19);
          v22 = v21;
          if( v21 )
          {
            _m_prefetchw(v21);
            HandleData = *v21;
LABEL_11:
            LowValue = HandleData.LowValue;
            while( (LowValue & 0x1FFFE) != 0 )
            {
              if( (LowValue & 1) == 0 )
              {
                ExpBlockOnLockedHandleEntry(v20, v22, LowValue);
                _m_prefetchw(v22);
                HandleData = *v22;
                goto LABEL_11;
              }
              v25.LowValue = LowValue;
              v25.HighValue = HandleData.HighValue;
              v26 = _InterlockedCompareExchange128(&v22->VolatileLowValue, v25.HighValue, LowValue - 2, &v25.LowValue);
              v24 = v25.LowValue;
              LowValue = v25.LowValue;
              HandleData = v25;
              if( v26 )
              {
                if( (unsigned __int16)((unsigned __int64)v24 >> 1) != 16 )
                {
                  v18 = (_OBJECT_HEADER *)((v24 >> 16) & 0xFFFFFFFFFFFFFFF0ui64);
                  v64 = (unsigned __int64)v18;
                  v16 = 1;
LABEL_17:
                  v14 = v59;
                  v17 = 0x140000000ui64;
                  goto LABEL_18;
                }
                HandleData.LowValue = v24 ^ ((unsigned int)v24 ^ (2 * (unsigned int)((unsigned __int64)v24 >> 1) - 2)) & 0x1FFFE;
                v18 = (_OBJECT_HEADER *)((HandleData.LowValue >> 16) & 0xFFFFFFFFFFFFFFF0ui64);
                v64 = (unsigned __int64)v18;
                ObpIncrPointerCountEx(v18, 32752i64);
                v52 = ExFastReplenishHandleTableEntry(v22, &HandleData, 32752i64);
                v16 = 1;
                if( !v52 )
                  goto LABEL_17;
                _InterlockedExchangeAdd64(&v18->PointerCount, -v52);
LABEL_58:
                v18 = (_OBJECT_HEADER *)v64;
                goto LABEL_17;
              }
            }
            if( ExLockHandleTableEntry(v20, v22) )
            {
              v64 = (v22->LowValue >> 16) & 0xFFFFFFFFFFFFFFF0ui64;
              v43 = (_OBJECT_HEADER *)v64;
              HandleData = *v22;
              v44 = ExSlowReplenishHandleTableEntry(v22);
              ObpIncrPointerCountEx(v43, (unsigned int)(v44 + 1));
              v16 = 1;
              _InterlockedExchangeAdd64(&v22->VolatileLowValue, 1ui64);
              _InterlockedOr(v58, 0);
              if( v20->HandleContentionEvent._bf_0 )
              {
                ExfUnblockPushLock(&v20->HandleContentionEvent._bf_0, 0i64);
                v16 = 1;
              }
              goto LABEL_58;
            }
            v18 = (_OBJECT_HEADER *)v64;
            v14 = v59;
            v16 = 1;
            v17 = 0x140000000ui64;
          }
        }
        if( v19 )
        {
          ExHandleLogBadReference(v20, v19.GenericHandleOverlay, KeGetCurrentThread()->PreviousMode);
          v18 = (_OBJECT_HEADER *)v64;
          v14 = v59;
          v16 = 1;
          v17 = 0x140000000ui64;
        }
        v22 = 0i64;
LABEL_18:
        v27 = v18;
        if( !v22 )
        {
LABEL_60:
          v37 = -1073741816;
LABEL_61:
          CurrentThread = Thread;
          v12 = 1;
          goto LABEL_62;
        }
        v28 = HandleData.LeafHandleValue.$E5B3C52FE72490EE6A49ADBB8529F30E::_bf_0 & 0x1FFFFFF;
        v71 = ++v9;
        p_Body = &v18->Body;
        v78[v15] = (__int64)&v18->Body;
        if( v14 == 1 )
        {
          if( (~v28 & 0x100000) != 0 )
          {
            v37 = -1073741790;
            goto LABEL_61;
          }
          if( (v18->InfoMask & 0x40) != 0 )
          {
            v51 = (char *)v18 - *(unsigned __int8 *)((v18->InfoMask & 0x7F) + v17 + 12737888);
            if( *(_BYTE *)(*(_QWORD *)v51 + 24i64) )
            {
              if( *(_QWORD *)(*(_QWORD *)v51 + 16i64) == 1i64 )
              {
                v37 = -1073700858;
                goto LABEL_61;
              }
              v18 = (_OBJECT_HEADER *)v64;
            }
          }
        }
        v30 = (unsigned __int64)v27 >> 8;
        v31 = WaitTypea;
        if( WaitTypea != WaitAny
          && *(POBJECT_TYPE *)(v17
                             + 8
                             * ((unsigned __int8)ObHeaderCookie ^ (unsigned __int8)v30 ^ (unsigned __int64)v18->TypeIndex)
                             + 13614720) == IoCompletionObjectType )
        {
          goto LABEL_60;
        }
        if( *(&WheapDeferredInternalLogsEventLock + 56)
          && *(_QWORD *)(v17
                       + 8 * ((unsigned __int8)ObHeaderCookie ^ (unsigned __int8)v30 ^ (unsigned __int64)v18->TypeIndex)
                       + 13614720) == *(&WheapDeferredInternalLogsEventLock + 56) )
        {
          v37 = -1073741788;
          goto LABEL_61;
        }
        if( ObpTraceFlags )
        {
          ObpPushStackInfo(v18, 1u, v16, 0x7457624Fui64);
          v16 = 1;
          v17 = 0x140000000ui64;
        }
        v32 = *(_QWORD *)(v17
                        + 8
                        * ((unsigned __int8)v30 ^ (unsigned __int8)ObHeaderCookie ^ (unsigned __int64)v18->TypeIndex)
                        + 13614720);
        v33 = *(_QWORD *)(v32 + 32);
        if( (v33 & 1) != 0 )
        {
          if( (v33 & 2) != 0 )
          {
            if( (*(_DWORD *)(v32 + 176) & *(_DWORD *)((_BYTE *)&p_Body->DoNotUseThisField
                                                     + *(unsigned __int16 *)(v32 + 180))) == *(_DWORD *)(v32 + 176) )
            {
              v33 = *(__int64 *)((char *)&p_Body->UseThisFieldToCopy + *(unsigned __int16 *)(v32 + 182));
            }
            else
            {
              v33 -= 3i64;
LABEL_28:
              v33 += (__int64)p_Body;
            }
          }
          else
          {
            v33 = *(__int64 *)((char *)p_Body + v33 - 1);
          }
        }
        else if( v33 >= 0 )
        {
          goto LABEL_28;
        }
        Object[v15] = (VOID *)v33;
        v15 = (unsigned int)(v15 + 1);
        v34 = Counta;
        if( (unsigned int)v15 >= Counta )
        {
          if( v60 )
          {
            v60 = 0;
            ExReleaseRundownProtection(v65 + 139);
          }
          CurrentThread = Thread;
          v35 = Thread->Tcb.KernelApcDisable++ == -1;
          if( v35
            && ($F25F8C4BA33AF922A5F1AF68CD89DDDF *)CurrentThread->Tcb.ApcState.ApcListHead[0].Flink != &CurrentThread->Tcb.152
            && !CurrentThread->Tcb.SpecialApcDisable )
          {
            KiCheckForKernelApcDelivery();
          }
          v12 = 0;
          v59 = 0;
          if( v31 == WaitAll && v34 > 1 )
          {
            v45 = &Object[1];
            v46 = 1;
            while( 2 )
            {
              v47 = v46;
              v48 = *v45;
              do
              {
                v49 = v47 - 1;
                v50 = Object[v49];
                if( v48 > v50 )
                  break;
                if( v48 == v50 )
                {
                  v37 = -1073741776;
                  goto LABEL_62;
                }
                Object[v47--] = v50;
              }
              while( (_DWORD)v49 );
              Object[v47] = v48;
              ++v46;
              ++v45;
              if( v46 < v34 )
                continue;
              break;
            }
          }
          v36 = P;
          v37 = KeWaitForMultipleObjects(v34, Object, v31, UserRequest, WaitMode, Alertable, v75, (_KWAIT_BLOCK *)P);
          Count_4 = v37;
          v38 = v65;
          goto LABEL_37;
        }
        v14 = v59;
        ObjectTable = v72;
        v7 = v74;
        continue;
      }
    }
  }
  v37 = -1073741558;
LABEL_62:
  v36 = P;
  v38 = v65;
LABEL_37:
  if( v9 )
  {
    v39 = (VOID **)&v78[v9];
    do
    {
      ObfDereferenceObjectWithTag(*--v39, 0x7457624Fui64);
      --v9;
    }
    while( v9 );
  }
  if( v12 )
  {
    if( v60 )
      ExReleaseRundownProtection(v38 + 139);
    KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  }
  if( v36 )
  {
    if( v61 )
    {
      if( Lookaside )
        ExFreeToNPagedLookasideList(Lookaside, v36);
      else
        ExFreePoolWithTag(v36, 0);
    }
    else
    {
      KeSetKernelStackSwapEnable(v62);
    }
  }
  return v37;
}

Referenced by:

NtWaitForMultipleObjects
NtWaitForMultipleObjects32