KeRemoveQueueEx

ULONG __stdcall KeRemoveQueueEx(
        PKQUEUE Queue,
        KPROCESSOR_MODE WaitMode,
        BOOLEAN Alertable,
        PLARGE_INTEGER Timeout,
        PLIST_ENTRY *EntryArray,
        ULONG Count){
  _ETHREAD *CurrentThread; 
  __int64 QuadPart; 
  __int64 v9; 
  unsigned __int8 CurrentIrql; 
  ULONG v12; 
  struct _KQUEUE *v13; 
  char v14; 
  struct _KPRCB *v15; 
  _LIST_ENTRY *v16; 
  __int64 v17; 
  int v18; 
  unsigned __int64 v19; 
  _LIST_ENTRY *p_WaitListHead; 
  _LIST_ENTRY *v21; 
  _LIST_ENTRY *v22; 
  unsigned int CurrentCount; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *p_EntryListHead; 
  __int64 v27; 
  _LIST_ENTRY *v28; 
  _LIST_ENTRY *Blink; 
  struct _KPRCB *CurrentPrcb; 
  unsigned __int64 v31; 
  ULONG_PTR v32; 
  int v33; 
  __int64 v34; 
  struct _KPRCB *v35; 
  unsigned __int64 v36; 
  ULONG_PTR v37; 
  __int64 v38; 
  unsigned __int64 v39; 
  struct _KPRCB *v40; 
  unsigned __int8 v41; 
  struct _KPRCB *v42; 
  __int64 v43; 
  __int64 v44; 
  __int64 v45; 
  struct _KPRCB *v46; 
  __int64 v47; 
  __int64 v48; 
  __int64 v49; 
  struct _KPRCB *v50; 
  __int64 v52; 
  int v53; 
  __int64 v54; 
  __int64 v55; 
  _ETHREAD **v56; 
  UINT64 SpinCount; 
  UINT64 v58; 
  UINT64 v59; 
  __int64 i; 
  __int64 v61; 
  int v63; 
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  QuadPart = 0i64;
  v9 = WaitMode;
  v61 = 0i64;
  if( !_bittestandreset((signed __int32 *)CurrentThread + 29, 2u) )
  {
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    *((_BYTE *)CurrentThread + 390) = CurrentIrql;
  }
  v12 = 1;
  if( Timeout )
  {
    if( Timeout->HighPart < 0 )
    {
      v63 = 2;
      QuadPart = *(_QWORD *)&KUSER_SHARED_DATA.InterruptTime.LowPart
               - KUSER_SHARED_DATA.InterruptTimeBias
               - (Timeout->QuadPart
                + *((_QWORD *)CurrentThread + 31));
    }
    else
    {
      QuadPart = Timeout->QuadPart;
      v63 = 1;
    }
  }
  else
  {
    v63 = 0;
  }
  v13 = (struct _KQUEUE *)*((_QWORD *)CurrentThread + 29);
  if( v13 == Queue )
  {
    if( Queue->Header.SignalState )
    {
      CurrentCount = Queue->CurrentCount;
      if( CurrentCount <= Queue->MaximumCount )
      {
        LODWORD(SpinCount) = 0;
        while( _interlockedbittestandset(&Queue->Header.Lock, 7u) )
        {
          do
            KeYieldProcessorEx(&SpinCount);
          while( (Queue->Header.LockNV & 0x80u) != 0 );
        }
        if( Queue->Header.SignalState && Queue->CurrentCount <= Queue->MaximumCount )
        {
          Flink = Queue->EntryListHead.Flink;
          p_EntryListHead = &Queue->EntryListHead;
          v27 = 0i64;
          do
          {
            --Queue->Header.SignalState;
            v28 = Flink->Flink;
            if( !Flink->Flink )
              KeBugCheckEx(0x96u, (ULONG_PTR)Flink, (ULONG_PTR)Queue, ExWorkerQueue, (ULONG_PTR)Flink[1].Flink);
            Blink = Flink->Blink;
            if( v28->Blink != Flink || Blink->Flink != Flink )
              goto LABEL_160;
            Blink->Flink = v28;
            v28->Blink = Blink;
            Flink->Flink = 0i64;
            EntryArray[v27] = Flink;
            v27 = (unsigned int)(v27 + 1);
            Flink = p_EntryListHead->Flink;
          }
          while( p_EntryListHead->Flink != p_EntryListHead && (unsigned int)v27 < Count );
          if( (_DWORD)v27 )
          {
            _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
            CurrentPrcb = KeGetCurrentPrcb();
            v31 = *((unsigned __int8 *)CurrentThread + 390);
            if( (unsigned __int8)v31 >= 2u )
            {
              if( *((_QWORD *)CurrentPrcb + 2) && !*((_BYTE *)CurrentPrcb + 12586) )
                KiRequestSoftwareInterrupt(CurrentPrcb, 2);
              return v27;
            }
            v32 = *((_QWORD *)CurrentPrcb + 1);
            if( *((_QWORD *)CurrentPrcb + 2) )
            {
              KiAbProcessContextSwitch(*((_KTHREAD **)CurrentPrcb + 1), 0i64);
              v42 = KeGetCurrentPrcb();
              HIDWORD(SpinCount) = 0;
              while( _interlockedbittestandset64((volatile signed __int32 *)CurrentPrcb + 12, 0i64) )
              {
                do
                  KeYieldProcessorEx((UINT64 *)((char *)&SpinCount + 4));
                while( *((_QWORD *)CurrentPrcb + 6) );
                v49 = *((_QWORD *)v42 + 4247);
                if( v49 && *((_BYTE *)v42 + 32) <= 1u )
                  ++*(_DWORD *)(v49 + 24);
              }
              v43 = *((_QWORD *)CurrentPrcb + 2);
              *((_QWORD *)CurrentPrcb + 2) = 0i64;
              _disable();
              KiEndThreadCycleAccumulation(CurrentPrcb, (_KTHREAD *)v32, 0i64);
              _enable();
              *((_QWORD *)CurrentPrcb + 1) = v43;
              if( *(_BYTE *)(v43 + 388) == 1 )
              {
                v44 = (unsigned int)(*(_DWORD *)(v43 + 132) - *(_DWORD *)(v43 + 436));
                *(_DWORD *)(v43 + 132) = v44 + KUSER_SHARED_DATA.TickCount.LowPart;
              }
              *(_BYTE *)(v43 + 388) = 2;
              *(_BYTE *)(v32 + 643) = 32;
              *(_BYTE *)(v32 + 390) = v31;
              KiQueueReadyThread((__int64)CurrentPrcb, v32, v44);
              if( !KiSwapContext((PKTHREAD)v32, (PKTHREAD)v43) )
                goto LABEL_51;
            }
            else if( (*(_DWORD *)(v32 + 116) & 0x40) == 0 )
            {
LABEL_51:
              __writecr8(v31);
              return v27;
            }
            __writecr8(1ui64);
            *(_DWORD *)(v32 + 116) &= ~0x40u;
            KiDeliverApc(0, 0i64, 0i64);
            goto LABEL_51;
          }
        }
        _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
        goto LABEL_9;
      }
    }
    if( Timeout && !Timeout->QuadPart )
    {
      if( (Queue->Header.Signalling & 1) != 0 )
      {
        *EntryArray = (PLIST_ENTRY)128;
      }
      else
      {
        if( Alertable )
        {
          v50 = KeGetCurrentPrcb();
          LODWORD(v58) = 0;
          while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
          {
            do
              KeYieldProcessorEx(&v58);
            while( *((_QWORD *)CurrentThread + 8) );
            v52 = *((_QWORD *)v50 + 4247);
            if( v52 && *((_BYTE *)v50 + 32) <= 1u )
            {
              v53 = *(_DWORD *)(v52 + 24) + 1;
              *(_DWORD *)(v52 + 24) = v53;
            }
          }
        }
        v33 = KiTestForAlertPending((__int64)CurrentThread, Alertable, v9, 1);
        v34 = v33;
        if( !v33 )
          v34 = 258i64;
        *EntryArray = (PLIST_ENTRY)v34;
        if( Alertable )
          KiReleaseThreadLockSafe((INT64)CurrentThread);
      }
      v35 = KeGetCurrentPrcb();
      v36 = *((unsigned __int8 *)CurrentThread + 390);
      if( (unsigned __int8)v36 >= 2u )
      {
        if( *((_QWORD *)v35 + 2) && !*((_BYTE *)v35 + 12586) )
          KiRequestSoftwareInterrupt(v35, 2);
        return v12;
      }
      v37 = *((_QWORD *)v35 + 1);
      if( *((_QWORD *)v35 + 2) )
      {
        KiAbProcessContextSwitch(*((_KTHREAD **)v35 + 1), 0i64);
        v46 = KeGetCurrentPrcb();
        HIDWORD(v58) = 0;
        while( _interlockedbittestandset64((volatile signed __int32 *)v35 + 12, 0i64) )
        {
          do
            KeYieldProcessorEx((UINT64 *)((char *)&v58 + 4));
          while( *((_QWORD *)v35 + 6) );
          v54 = *((_QWORD *)v46 + 4247);
          if( v54 && *((_BYTE *)v46 + 32) <= 1u )
            ++*(_DWORD *)(v54 + 24);
        }
        v47 = *((_QWORD *)v35 + 2);
        *((_QWORD *)v35 + 2) = 0i64;
        _disable();
        KiEndThreadCycleAccumulation(v35, (_KTHREAD *)v37, 0i64);
        _enable();
        *((_QWORD *)v35 + 1) = v47;
        if( *(_BYTE *)(v47 + 388) == 1 )
        {
          v48 = (unsigned int)(*(_DWORD *)(v47 + 132) - *(_DWORD *)(v47 + 436));
          *(_DWORD *)(v47 + 132) = v48 + KUSER_SHARED_DATA.TickCount.LowPart;
        }
        *(_BYTE *)(v47 + 388) = 2;
        *(_BYTE *)(v37 + 643) = 32;
        *(_BYTE *)(v37 + 390) = v36;
        KiQueueReadyThread((__int64)v35, v37, v48);
        if( !KiSwapContext((PKTHREAD)v37, (PKTHREAD)v47) )
          goto LABEL_64;
      }
      else if( (*(_DWORD *)(v37 + 116) & 0x40) == 0 )
      {
LABEL_64:
        __writecr8(v36);
        return v12;
      }
      __writecr8(1ui64);
      *(_DWORD *)(v37 + 116) &= ~0x40u;
      KiDeliverApc(0, 0i64, 0i64);
      goto LABEL_64;
    }
  }
LABEL_9:
  for( i = *((unsigned __int8 *)CurrentThread + 390); ; *((_BYTE *)CurrentThread + 390) = i )
  {
    v14 = i;
    while( 1 )
    {
      *((_DWORD *)CurrentThread + 29) &= ~0x10u;
      *((_BYTE *)CurrentThread + 112) = 0;
      *((_BYTE *)CurrentThread + 391) = v9;
      if( Alertable )
        *((_DWORD *)CurrentThread + 29) |= 0x10u;
      v15 = KeGetCurrentPrcb();
      LODWORD(v59) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
      {
        do
          KeYieldProcessorEx(&v59);
        while( *((_QWORD *)CurrentThread + 8) );
        v45 = *((_QWORD *)v15 + 4247);
        if( v45 && *((_BYTE *)v15 + 32) <= 1u )
          ++*(_DWORD *)(v45 + 24);
      }
      if( !*((_BYTE *)CurrentThread + 193) || *((_WORD *)CurrentThread + 243) || v14 )
        break;
      KiReleaseThreadLockSafe((INT64)CurrentThread);
      __writecr8(1ui64);
      KiDeliverApc(0, 0i64, 0i64);
      KeGetCurrentIrql();
      __writecr8(2ui64);
      *((_BYTE *)CurrentThread + 390) = 0;
    }
    v16 = (_LIST_ENTRY *)((char *)CurrentThread + 320);
    if( !Alertable )
    {
      if( (*((_BYTE *)CurrentThread + 194) & 2) == 0 || !(_BYTE)v9 )
      {
LABEL_21:
        *((_BYTE *)CurrentThread + 388) = 5;
        *((_BYTE *)CurrentThread + 643) = 15;
        *((_DWORD *)CurrentThread + 109) = KUSER_SHARED_DATA.TickCount.LowPart;
        *((_QWORD *)CurrentThread + 8) = 0i64;
        v17 = 0i64;
        goto LABEL_22;
      }
      goto LABEL_91;
    }
    if( *((_BYTE *)CurrentThread + v9 + 114) )
    {
      *((_BYTE *)CurrentThread + v9 + 114) = 0;
      v17 = 257i64;
      goto LABEL_92;
    }
    if( (_BYTE)v9 && *((_ETHREAD **)CurrentThread + 21) != (_ETHREAD *)((char *)CurrentThread + 168) )
    {
      *((_BYTE *)CurrentThread + 194) |= 2u;
LABEL_91:
      v17 = 192i64;
      goto LABEL_92;
    }
    if( !*((_BYTE *)CurrentThread + 114) )
      goto LABEL_21;
    *((_BYTE *)CurrentThread + 114) = 0;
    v17 = 257i64;
LABEL_92:
    KiReleaseThreadLockSafe((INT64)CurrentThread);
    KiCheckForThreadDispatch(KeGetCurrentPrcb(), i);
LABEL_22:
    if( v17 )
    {
      *EntryArray = (PLIST_ENTRY)v17;
      return v12;
    }
    if( Queue != *((PKQUEUE *)CurrentThread + 29) )
      KiSwitchQueue(CurrentThread, Queue);
    *((_BYTE *)CurrentThread + 336) = 3;
    *((_BYTE *)CurrentThread + 337) = 4;
    v18 = 0;
    *((_WORD *)CurrentThread + 169) = 128;
    *((_QWORD *)CurrentThread + 44) = Queue;
    while( _interlockedbittestandset(&Queue->Header.Lock, 7u) )
    {
      do
      {
        ++v18;
        _mm_pause();
      }
      while( (Queue->Header.LockNV & 0x80u) != 0 );
    }
    if( Queue->Header.SignalState )
    {
      if( Queue->CurrentCount <= Queue->MaximumCount )
      {
        LODWORD(v27) = KiAttemptFastRemoveQueue(Queue, EntryArray, Count);
        if( (_DWORD)v27 )
        {
          _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
          goto LABEL_85;
        }
      }
    }
    if( (Queue->Header.Signalling & 1) != 0 )
      break;
    v19 = QuadPart;
    if( v63 == 2 )
    {
      v38 = *((unsigned int *)CurrentThread + 238);
      v39 = *(_QWORD *)&KUSER_SHARED_DATA.InterruptTime.LowPart
          - *((_QWORD *)CurrentThread + 31)
          - KUSER_SHARED_DATA.InterruptTimeBias;
      v19 = QuadPart;
      if( *((_BYTE *)CurrentThread + 391)
        && !*((_DWORD *)CurrentThread + 121)
        && !*((_BYTE *)CurrentThread + 390)
        && !*((_BYTE *)CurrentThread + 192)
        && (_DWORD)v38 )
      {
        v19 = v38 + QuadPart;
      }
    }
    else
    {
      if( !v63 )
        goto LABEL_30;
      if( !QuadPart )
      {
LABEL_106:
        _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
        *EntryArray = (PLIST_ENTRY)258;
        goto LABEL_107;
      }
      v39 = *(_QWORD *)&KUSER_SHARED_DATA.SystemTime.LowPart;
    }
    if( v39 > v19 )
      goto LABEL_106;
LABEL_30:
    _InterlockedDecrement((volatile signed __int32 *)&Queue->CurrentCount);
    p_WaitListHead = &Queue->Header.WaitListHead;
    v21 = Queue->Header.WaitListHead.Flink;
    if( v21->Blink != &Queue->Header.WaitListHead )
      goto LABEL_160;
    v16->Flink = v21;
    *((_QWORD *)CurrentThread + 41) = p_WaitListHead;
    v21->Blink = v16;
    p_WaitListHead->Flink = v16;
    _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
    *((_BYTE *)CurrentThread + 587) = 1;
    v22 = (_LIST_ENTRY *)KiCommitThreadWait((__int64)CurrentThread, (__int64 *)CurrentThread + 40, v63, QuadPart, 0i64);
    *((_BYTE *)CurrentThread + 643) = 0;
    if( v22 != (_LIST_ENTRY *)256 )
    {
      *EntryArray = v22;
      if( Count > 1
        && (unsigned __int64)&v22[-17].Blink + 7 > 1
        && v22 != (_LIST_ENTRY *)128
        && v22 != (_LIST_ENTRY *)192
        && Queue->Header.SignalState )
      {
        v41 = KeGetCurrentIrql();
        __writecr8(2ui64);
        KiAcquireKobjectLockSafe(Queue);
        if( Queue->Header.SignalState )
          v12 = KiAttemptFastRemoveQueue(Queue, EntryArray + 1, Count - 1) + 1;
        _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
        __writecr8(v41);
      }
      return v12;
    }
    i = KeGetCurrentIrql();
    __writecr8(2ui64);
  }
  if( !*((_QWORD *)CurrentThread + 29) )
    goto LABEL_159;
  v55 = *((_QWORD *)CurrentThread + 65);
  v56 = (_ETHREAD **)*((_QWORD *)CurrentThread + 66);
  if( *(_ETHREAD **)(v55 + 8) != (_ETHREAD *)((char *)CurrentThread + 520)
    || *v56 != (_ETHREAD *)((char *)CurrentThread + 520) )
  {
LABEL_160:
    __fastfail(3u);
  }
  *v56 = (_ETHREAD *)v55;
  *(_QWORD *)(v55 + 8) = v56;
  *((_QWORD *)CurrentThread + 29) = 0i64;
LABEL_159:
  _InterlockedAnd(&Queue->Header.Lock, 0xFFFFFF7F);
  *EntryArray = (PLIST_ENTRY)128;
LABEL_107:
  LODWORD(v27) = 1;
LABEL_85:
  *((_BYTE *)CurrentThread + 643) = 0;
  v40 = KeGetCurrentPrcb();
  if( *((_QWORD *)v40 + 1441) )
    KiProcessThreadWaitList((struct KPRCB *)v40, 1, 0);
  KiFastExitThreadWait((__int64)v40, (__int64)CurrentThread, 1);
  return v27;
}

Referenced by:

IoRemoveIoCompletion
KeRemoveQueue