ObWaitForMultipleObjects

INT64 __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; 
  struct _EX_RUNDOWN_REF *v11; 
  char v12; 
  unsigned __int64 v13; 
  INT8 v14; 
  __int64 v15; 
  unsigned int v16; 
  unsigned __int64 v17; 
  unsigned __int64 v18; 
  ULONG_PTR v19; 
  _HANDLE_TABLE *v20; 
  _HANDLE_TABLE_ENTRY *v21; 
  _HANDLE_TABLE_ENTRY *v22; 
  INT64 v23; 
  __int64 v24; 
  __int128 v25; 
  unsigned __int8 v26; 
  unsigned __int64 v27; 
  int v28; 
  unsigned __int64 v29; 
  unsigned __int64 v30; 
  WAIT_TYPE v31; 
  __int64 v32; 
  __int64 v33; 
  ULONG v34; 
  bool v35; 
  PKWAIT_BLOCK v36; 
  int v37; 
  unsigned int v38; 
  struct _EX_RUNDOWN_REF *v39; 
  PVOID *v40; 
  unsigned __int64 v42; 
  struct _KWAIT_BLOCK *PoolWithTag; 
  volatile INT64 *v44; 
  int v45; 
  void **v46; 
  unsigned int v47; 
  unsigned int v48; 
  void *v49; 
  __int64 v50; 
  void *v51; 
  unsigned __int64 v52; 
  int v53; 
  __int64 v54; 
  void *v55; 
  unsigned int v56; 
  PVOID *v57; 
  __int64 v58; 
  int v59[8]; 
  INT8 v60; 
  char v61; 
  char v62; 
  UINT8 v63; 
  PKWAIT_BLOCK WaitBlockArray; 
  unsigned __int64 v65; 
  struct _EX_RUNDOWN_REF *v66; 
  _ETHREAD *v67; 
  INT64 CurrentValue[2]; 
  WAIT_TYPE WaitTypea; 
  ULONG Counta; 
  int v71; 
  int v72; 
  unsigned __int64 v73; 
  PNPAGED_LOOKASIDE_LIST Lookaside; 
  VOID **v75; 
  PLARGE_INTEGER v76; 
  struct _EX_RUNDOWN_REF *v77; 
  PVOID Object; 
  char v79; 
  __int64 result[64]; 
  WaitTypea = WaitType;
  v60 = AccessMode;
  v7 = CapturedHandles;
  v75 = CapturedHandles;
  v8 = (unsigned int)Count;
  Counta = Count;
  v76 = Timeout;
  *(_OWORD *)CurrentValue = 0i64;
  memset((INT64)result, 0i64);
  v65 = 0i64;
  memset((INT64)&Object, 0i64);
  v63 = 0;
  v62 = 0;
  WaitBlockArray = 0i64;
  v9 = 0;
  Lookaside = 0i64;
  if( (unsigned int)v8 > 3 )
  {
    v42 = 48 * v8;
    if( (unsigned int)v8 > 0xA )
    {
      Lookaside = (PNPAGED_LOOKASIDE_LIST)&ObpWaitBlockLookaside[16 * (unsigned __int64)(((int)v8 - 11) / 0xEu)];
      LODWORD(PoolWithTag) = ExAllocateFromNPagedLookasideList(Lookaside);
    }
    else
    {
      PoolWithTag = (struct _KWAIT_BLOCK *)ExAllocatePoolWithTag(NonPagedPoolNx, 48 * v8, 0x6D57624Fui64);
    }
    WaitBlockArray = PoolWithTag;
    if( PoolWithTag )
    {
      v62 = 1;
    }
    else
    {
      v63 = KeSetKernelStackSwapEnable(0);
      v54 = v42 + 15;
      if( v42 + 15 <= v42 )
        v54 = 0xFFFFFFFFFFFFFF0i64;
      v55 = alloca(v54 & 0xFFFFFFFFFFFFFFF0ui64);
      WaitBlockArray = (PKWAIT_BLOCK)&v60;
    }
  }
  v61 = 0;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v67 = CurrentThread;
  v11 = (struct _EX_RUNDOWN_REF *)*((_QWORD *)CurrentThread + 23);
  v66 = v11;
  v77 = v11;
  v12 = 1;
  --*((_WORD *)CurrentThread + 242);
  if( v11 == *((struct _EX_RUNDOWN_REF **)CurrentThread + 68) )
  {
    v13 = v11[174].Count;
    v73 = v13;
LABEL_4:
    v14 = v60;
    goto LABEL_5;
  }
  v13 = ObReferenceProcessHandleTable(v11);
  v73 = v13;
  if( v13 )
  {
    v61 = 1;
    goto LABEL_4;
  }
  v56 = 0;
  if( !(_DWORD)v8 )
    goto LABEL_4;
  v57 = v7;
  v14 = v60;
  while( ObpIsKernelHandle(*v57, v14) )
  {
    ++v56;
    v57 = (PVOID *)(v58 + 8);
    if( v56 >= (unsigned int)v8 )
    {
      v13 = v73;
LABEL_5:
      v15 = 0i64;
      v16 = 1;
      v17 = 0x140000000ui64;
      v18 = v65;
      while( 2 )
      {
        v19 = (ULONG_PTR)v7[v15];
        if( v14 || (v19 & 0xFFFFFFFF80000000ui64) != 0xFFFFFFFF80000000ui64 || v19 > 0xFFFFFFFFFFFFFFFDui64 )
        {
          v20 = (_HANDLE_TABLE *)v13;
        }
        else
        {
          v19 ^= 0xFFFFFFFF80000000ui64;
          v20 = (_HANDLE_TABLE *)ObpKernelHandleTable;
        }
        if( (v19 & 0x3FC) != 0 )
        {
          v21 = ExpLookupHandleTableEntry(v20, (_EXHANDLE)v19);
          v22 = v21;
          if( v21 )
          {
            _m_prefetchw(v21);
            CurrentValue[0] = v21->LowValue;
            CurrentValue[1] = v21->HighValue;
LABEL_11:
            v23 = CurrentValue[0];
            while( (v23 & 0x1FFFE) != 0 )
            {
              if( (v23 & 1) == 0 )
              {
                ExpBlockOnLockedHandleEntry(v20, v22, v23);
                _m_prefetchw(v22);
                CurrentValue[0] = v22->LowValue;
                CurrentValue[1] = v22->HighValue;
                goto LABEL_11;
              }
              *(_QWORD *)&v25 = v23;
              *((_QWORD *)&v25 + 1) = CurrentValue[1];
              v26 = _InterlockedCompareExchange128(
                      &v22->VolatileLowValue,
                      *((signed __int64 *)&v25 + 1),
                      v23 - 2,
                      (signed __int64 *)&v25);
              v24 = v25;
              v23 = v25;
              *(_OWORD *)CurrentValue = v25;
              if( v26 )
              {
                if( (unsigned __int16)((unsigned __int64)v24 >> 1) != 16 )
                {
                  v18 = (v24 >> 16) & 0xFFFFFFFFFFFFFFF0ui64;
                  v65 = v18;
                  v16 = 1;
LABEL_17:
                  v14 = v60;
                  v17 = 0x140000000ui64;
                  goto LABEL_18;
                }
                CurrentValue[0] = v24 ^ ((unsigned int)v24 ^ (2 * (unsigned int)((unsigned __int64)v24 >> 1) - 2)) & 0x1FFFE;
                v18 = (CurrentValue[0] >> 16) & 0xFFFFFFFFFFFFFFF0ui64;
                v65 = v18;
                ObpIncrPointerCountEx((volatile INT64 *)v18, 32752i64);
                v53 = ExFastReplenishHandleTableEntry(&v22->VolatileLowValue, (unsigned __int64 *)CurrentValue, 32752);
                v16 = 1;
                if( !v53 )
                  goto LABEL_17;
                _InterlockedExchangeAdd64((volatile signed __int64 *)v18, -v53);
LABEL_58:
                v18 = v65;
                goto LABEL_17;
              }
            }
            if( ExLockHandleTableEntry((__int64)v20, &v22->LowValue) )
            {
              v65 = (v22->LowValue >> 16) & 0xFFFFFFFFFFFFFFF0ui64;
              v44 = (volatile INT64 *)v65;
              *(_HANDLE_TABLE_ENTRY *)CurrentValue = *v22;
              v45 = ExSlowReplenishHandleTableEntry((unsigned __int64 *)v22);
              ObpIncrPointerCountEx(v44, (unsigned int)(v45 + 1));
              v16 = 1;
              _InterlockedExchangeAdd64(&v22->VolatileLowValue, 1ui64);
              _InterlockedOr(v59, 0);
              if( v20->HandleContentionEvent.Value )
              {
                ExfUnblockPushLock(&v20->HandleContentionEvent, 0i64);
                v16 = 1;
              }
              goto LABEL_58;
            }
            v18 = v65;
            v14 = v60;
            v16 = 1;
            v17 = 0x140000000ui64;
          }
        }
        if( v19 )
        {
          ExHandleLogBadReference((ULONG_PTR)v20, v19, *((_BYTE *)KeGetCurrentThread() + 562));
          v18 = v65;
          v14 = v60;
          v16 = 1;
          v17 = 0x140000000ui64;
        }
        v22 = 0i64;
LABEL_18:
        v27 = v18;
        if( !v22 )
        {
LABEL_60:
          v38 = -1073741816;
LABEL_61:
          CurrentThread = v67;
          v12 = 1;
          goto LABEL_62;
        }
        v28 = CurrentValue[1] & 0x1FFFFFF;
        v72 = ++v9;
        v29 = v18 + 48;
        result[v15] = v18 + 48;
        if( v14 == 1 )
        {
          if( (~v28 & 0x100000) != 0 )
          {
            v38 = -1073741790;
            goto LABEL_61;
          }
          if( (*(_BYTE *)(v18 + 26) & 0x40) != 0 )
          {
            v52 = v18 - *(unsigned __int8 *)((*(_BYTE *)(v18 + 26) & 0x7F) + v17 + 12737888);
            if( *(_BYTE *)(*(_QWORD *)v52 + 24i64) )
            {
              if( *(_QWORD *)(*(_QWORD *)v52 + 16i64) == 1i64 )
              {
                v38 = -1073700858;
                goto LABEL_61;
              }
              v18 = v65;
            }
          }
        }
        v30 = v27 >> 8;
        v31 = WaitTypea;
        if( WaitTypea != WaitAny
          && *(POBJECT_TYPE *)(v17
                             + 8
                             * ((unsigned __int8)ObHeaderCookie ^ (unsigned __int8)v30 ^ (unsigned __int64)*(unsigned __int8 *)(v18 + 24))
                             + 13614720) == IoCompletionObjectType )
        {
          goto LABEL_60;
        }
        if( ExCrossVmMutantObjectType
          && *(POBJECT_TYPE *)(v17
                             + 8
                             * ((unsigned __int8)ObHeaderCookie ^ (unsigned __int8)v30 ^ (unsigned __int64)*(unsigned __int8 *)(v18 + 24))
                             + 13614720) == ExCrossVmMutantObjectType )
        {
          v38 = -1073741788;
          goto LABEL_61;
        }
        if( ObpTraceFlags )
        {
          ObpPushStackInfo(v18, 1, v16, 1951883855i64);
          v16 = 1;
          v17 = 0x140000000ui64;
        }
        v32 = *(_QWORD *)(v17
                        + 8
                        * ((unsigned __int8)v30 ^ (unsigned __int8)ObHeaderCookie ^ (unsigned __int64)*(unsigned __int8 *)(v18 + 24))
                        + 13614720);
        v33 = *(_QWORD *)(v32 + 32);
        if( (v33 & 1) != 0 )
        {
          if( (v33 & 2) != 0 )
          {
            if( (*(_DWORD *)(v32 + 176) & *(_DWORD *)(*(unsigned __int16 *)(v32 + 180) + v29)) == *(_DWORD *)(v32 + 176) )
            {
              v33 = *(_QWORD *)(*(unsigned __int16 *)(v32 + 182) + v29);
            }
            else
            {
              v33 -= 3i64;
LABEL_28:
              v33 += v29;
            }
          }
          else
          {
            v33 = *(_QWORD *)(v29 + v33 - 1);
          }
        }
        else if( v33 >= 0 )
        {
          goto LABEL_28;
        }
        *(&Object + v15) = (PVOID)v33;
        v15 = (unsigned int)(v15 + 1);
        v34 = Counta;
        if( (unsigned int)v15 >= Counta )
        {
          if( v61 )
          {
            v61 = 0;
            ExReleaseRundownProtection(v66 + 139);
          }
          CurrentThread = v67;
          v35 = (*((_WORD *)v67 + 242))++ == 0xFFFF;
          if( v35
            && *((_ETHREAD **)CurrentThread + 19) != (_ETHREAD *)((char *)CurrentThread + 152)
            && !*((_WORD *)CurrentThread + 243) )
          {
            KiCheckForKernelApcDelivery();
          }
          v12 = 0;
          v60 = 0;
          if( v31 == WaitAll && v34 > 1 )
          {
            v46 = (void **)&v79;
            v47 = 1;
            while( 2 )
            {
              v48 = v47;
              v49 = *v46;
              do
              {
                v50 = v48 - 1;
                v51 = *(&Object + v50);
                if( v49 > v51 )
                  break;
                if( v49 == v51 )
                {
                  v38 = -1073741776;
                  goto LABEL_62;
                }
                *(&Object + v48--) = v51;
              }
              while( (_DWORD)v50 );
              *(&Object + v48) = v49;
              ++v47;
              ++v46;
              if( v47 < v34 )
                continue;
              break;
            }
          }
          v36 = WaitBlockArray;
          KeWaitForMultipleObjects((_BYTE *)v34, &Object, v31, UserRequest, WaitMode, Alertable, v76, WaitBlockArray);
          v38 = v37;
          v71 = v37;
          v39 = v66;
          goto LABEL_37;
        }
        v14 = v60;
        v13 = v73;
        v7 = v75;
        continue;
      }
    }
  }
  v38 = -1073741558;
LABEL_62:
  v36 = WaitBlockArray;
  v39 = v66;
LABEL_37:
  if( v9 )
  {
    v40 = (PVOID *)&result[v9];
    do
    {
      ObfDereferenceObjectWithTag(*--v40, 0x7457624Fui64);
      --v9;
    }
    while( v9 );
  }
  if( v12 )
  {
    if( v61 )
      ExReleaseRundownProtection(v39 + 139);
    KeLeaveCriticalRegionThread((__int64)CurrentThread);
  }
  if( v36 )
  {
    if( v62 )
    {
      if( Lookaside )
        ExFreeToNPagedLookasideList(Lookaside, v36);
      else
        ExFreePoolWithTag(v36, 0);
    }
    else
    {
      KeSetKernelStackSwapEnable(v63);
    }
  }
  return v38;
}

Referenced by:

NtWaitForMultipleObjects
NtWaitForMultipleObjects32