KiExpireTimer2

VOID __stdcall KiExpireTimer2(_KTIMER2 *Timer, _KPRCB *Prcb, UINT64 CurrentTime, _KDPC_TRACKER_TABLE *DpcTracker){
  _ETHREAD *CurrentThread; 
  UINT64 v6; 
  _KPRCB *v7; 
  int v8; 
  __int64 Period; 
  _KTIMER2 *v10; 
  char v11; 
  _KTIMER2 *v12; 
  __int64 v13; 
  _KWAIT_BLOCK *v14; 
  _LIST_ENTRY *Blink; 
  unsigned __int8 TypeFlags; 
  unsigned __int64 v17; 
  char v18; 
  unsigned __int64 v19; 
  unsigned __int8 WaitType; 
  _ETHREAD *Thread; 
  _QWORD *v22; 
  struct _KPRCB *CurrentPrcb; 
  char v24; 
  bool v25; 
  void(__fastcall *v26)(_KTIMER2 *, unsigned __int64); 
  int v27; 
  int v28; 
  signed __int32 v29; 
  signed __int32 v30; 
  int v31; 
  _KWAIT_BLOCK **QuantumTarget; 
  unsigned __int64 v33; 
  _KDPC_TRACKER_TABLE *v34; 
  INT64 v35; 
  INT64 v36; 
  __int64 v37; 
  _KDPC_TRACKER_TABLE *v38; 
  signed __int32 v39; 
  signed __int32 v40; 
  unsigned __int64 v41; 
  unsigned __int64 v42; 
  _KTIMER2 *v43; 
  _KTIMER2 *v44; 
  bool v45; 
  _KTIMER2 *v46; 
  unsigned __int64 v47; 
  UINT64 v48; 
  unsigned __int8 v49; 
  unsigned __int64 v50; 
  __int64 v51; 
  unsigned __int64 v52; 
  unsigned __int64 v53; 
  unsigned __int64 v54; 
  _KWAIT_BLOCK *v55; 
  unsigned __int8 v56; 
  INT64 WaitKey; 
  _ETHREAD *v58; 
  _QWORD *v59; 
  _ETHREAD *v60; 
  _KPRCB *v61; 
  char v62; 
  int v63; 
  _KWAIT_BLOCK **v64; 
  signed __int32 v65; 
  UINT8 WasLate; 
  char v67; 
  _KPRCB *Prcba; 
  _ETHREAD *v69; 
  INT64 v70; 
  PVOID BugCheckParameter3; 
  INT64 CurrentQpc; 
  _KDPC_TRACKER_TABLE *v73; 
  __int64 Data; 
  __int64 v75; 
  __int64 v76; 
  __int64 v77; 
  __int64 v78; 
  __int64 v79; 
  __int64 v80; 
  _LARGE_INTEGER TimeStamp[2]; 
  __int128 v82; 

  CurrentThread = Prcb->CurrentThread;
  v73 = DpcTracker;
  v70 = (INT64)Prcb;
  v6 = CurrentTime;
  Data = 0i64;
  v7 = Prcb;
  v75 = 0i64;
  v8 = 0;
  v77 = 0i64;
  v78 = 0i64;
  v79 = 0i64;
  v80 = 0i64;
  *(_OWORD *)&TimeStamp[0].anonymous_0.LowPart = 0i64;
  CurrentQpc = 0i64;
  v82 = 0i64;
  LODWORD(BugCheckParameter3) = CurrentThread->Tcb.WaitBlock[3].SpareLong;
  v76 = 0i64;
  WasLate = 0;
  v69 = CurrentThread;
  Period = Timer->Period;
  if( !Period || (Timer->gap0[1] & 0x20) != 0 )
    goto LABEL_2;
  TypeFlags = Timer->TypeFlags;
  if( (TypeFlags & 4) != 0 )
  {
    LODWORD(v48) = RtlGetInterruptTimePrecise(&CurrentQpc);
    Period = Timer->Period;
    v6 = v48;
    TypeFlags = Timer->TypeFlags;
  }
  v17 = Period + v6;
  if( Period + v6 < v6 || v17 == -1i64 )
  {
    v17 = -2i64;
    v18 = 1;
  }
  else
  {
    v18 = 0;
  }
  v67 = v18;
  if( (TypeFlags & 0xE) == 0 )
  {
    if( (KiVelocityFlags & 0x2000) != 0 )
    {
      v43 = *(_KTIMER2 **)&Timer->gap0[8];
      v44 = (_KTIMER2 *)&Timer->gap0[8];
      if( v43 == (_KTIMER2 *)&Timer->gap0[8] )
      {
LABEL_54:
        if( (TypeFlags & 0x10) == 0 )
          goto LABEL_13;
        v49 = TypeFlags & 0xEF;
        goto LABEL_69;
      }
      while( 1 )
      {
        v45 = v43->gap0[16] <= 1u;
        v46 = v43;
        v43 = *(_KTIMER2 **)v43->gap0;
        if( v45 )
        {
          if( PsTimerResolutionActive(*(_QWORD *)(*(_QWORD *)&v46->gap0[24] + 544i64)) )
            break;
        }
        if( v43 == v44 )
          goto LABEL_54;
      }
      if( (TypeFlags & 0x10) != 0 )
        goto LABEL_13;
    }
    else if( (TypeFlags & 0x10) != 0 )
    {
      goto LABEL_13;
    }
    v49 = TypeFlags | 0x10;
LABEL_69:
    Timer->TypeFlags = v49;
    KiUpdateTimer2Collections(Timer);
  }
LABEL_13:
  v19 = Timer->DueTime[1];
  if( v19 != -1i64 )
  {
    v41 = v19 - Timer->DueTime[0];
    if( v41 )
    {
      v47 = v41 + v6;
      if( v41 + v6 < v6 || v47 == -1i64 )
        v47 = -2i64;
      v42 = v47 + Timer->Period;
      if( v42 < v47 || v42 == -1i64 )
        v42 = -2i64;
    }
    else
    {
      v42 = v17;
    }
    Timer->DueTime[1] = v42;
  }
  Timer->DueTime[0] = v17;
  while( !KiInsertTimer2(Timer, 0, &WasLate) )
  {
    if( v18 )
      goto LABEL_2;
    v50 = Timer->DueTime[0];
    v51 = Timer->Period;
    v52 = v50 + v51;
    if( v50 + v51 < v50 || v52 == -1i64 )
    {
      v52 = -2i64;
      v18 = 1;
    }
    Timer->DueTime[0] = v52;
    v53 = Timer->DueTime[1];
    v67 = v18;
    if( v53 != -1i64 )
    {
      v54 = v53 + v51;
      if( v53 + v51 < v53 || v54 == -1i64 )
        v54 = -2i64;
      Timer->DueTime[1] = v54;
    }
  }
  v8 = 1;
LABEL_2:
  v10 = (_KTIMER2 *)&Timer->gap0[8];
  v11 = Timer->gap0[0] & 0x7F;
  v12 = *(_KTIMER2 **)&Timer->gap0[8];
  *(_DWORD *)&Timer->gap0[4] = 1;
  if( v11 == 25 )
  {
    if( v12 == v10 )
      goto LABEL_26;
    while( 1 )
    {
      v13 = *(_QWORD *)v12->gap0;
      v14 = (_KWAIT_BLOCK *)v12;
      v12 = (_KTIMER2 *)v13;
      Blink = v14->WaitListEntry.Blink;
      if( *(_KWAIT_BLOCK **)(v13 + 8) != v14 || (_KWAIT_BLOCK *)Blink->Flink != v14 )
        goto LABEL_5;
      Blink->Flink = (_LIST_ENTRY *)v13;
      *(_QWORD *)(v13 + 8) = Blink;
      WaitType = v14->WaitType;
      if( WaitType == 1 )
      {
        if( KiTryUnwaitThread(v7, v14, v14->WaitKey, 0i64) )
        {
          v25 = (*(_DWORD *)&Timer->gap0[4])-- == 1;
          if( v25 )
          {
LABEL_25:
            CurrentThread = v69;
            goto LABEL_26;
          }
        }
      }
      else if( WaitType == 2 )
      {
        v14->BlockState = 5;
        Thread = v14->Thread;
        v14->WaitListEntry.Flink = 0i64;
        v22 = &Thread->Tcb.gap0[8];
        KeGetCurrentIrql();
        __writecr8(2ui64);
        CurrentPrcb = KeGetCurrentPrcb();
        Prcba = (_KPRCB *)CurrentPrcb->CurrentThread;
        KiAcquireKobjectLockSafe(Thread);
        if( (_QWORD *)*v22 == v22
          || LODWORD(Thread->Tcb.InitialStack) >= HIDWORD(Thread->Tcb.InitialStack)
          || *(_ETHREAD **)&Prcba->CFlushSize == Thread && BYTE3(Prcba->ProcessorState.ContextFrame._Rbx) == 15
          || (KiWakeQueueWaiter(CurrentPrcb, (_KQUEUE *)Thread, (INT64)v14), !v24) )
        {
          v31 = *(_DWORD *)&Thread->Tcb.gap0[4];
          *(_DWORD *)&Thread->Tcb.gap0[4] = v31 + 1;
          QuantumTarget = (_KWAIT_BLOCK **)Thread->Tcb.QuantumTarget;
          if( *QuantumTarget != (_KWAIT_BLOCK *)&Thread->Tcb.SListFaultAddress )
            goto LABEL_5;
          v14->WaitListEntry.Flink = (_LIST_ENTRY *)&Thread->Tcb.SListFaultAddress;
          v14->WaitListEntry.Blink = (_LIST_ENTRY *)QuantumTarget;
          *QuantumTarget = v14;
          Thread->Tcb.QuantumTarget = (unsigned __int64)v14;
          if( !v31 && (_QWORD *)*v22 != v22 )
            KiWakeOtherQueueWaiters(CurrentPrcb, (_KQUEUE *)Thread);
        }
        _InterlockedAnd((volatile signed __int32 *)Thread, 0xFFFFFF7F);
        v25 = (*(_DWORD *)&Timer->gap0[4])-- == 1;
        v7 = (_KPRCB *)v70;
        if( v25 )
          goto LABEL_25;
      }
      else
      {
        KiTryUnwaitThread(v7, v14, 256i64, 0i64);
      }
      if( v12 == (_KTIMER2 *)&Timer->gap0[8] )
        goto LABEL_25;
    }
  }
  if( v12 != v10 )
  {
    while( 1 )
    {
      v55 = (_KWAIT_BLOCK *)v12;
      v12 = *(_KTIMER2 **)v12->gap0;
      v56 = v55->WaitType;
      if( v56 == 1 )
      {
        WaitKey = v55->WaitKey;
LABEL_98:
        KiTryUnwaitThread(v7, v55, WaitKey, 0i64);
        goto LABEL_99;
      }
      if( v56 != 2 )
      {
        WaitKey = 256i64;
        goto LABEL_98;
      }
      v55->BlockState = 5;
      v58 = v55->Thread;
      v55->WaitListEntry.Flink = 0i64;
      v59 = &v58->Tcb.gap0[8];
      KeGetCurrentIrql();
      __writecr8(2ui64);
      Prcba = KeGetCurrentPrcb();
      v60 = Prcba->CurrentThread;
      KiAcquireKobjectLockSafe(v58);
      if( (_QWORD *)*v59 == v59
        || LODWORD(v58->Tcb.InitialStack) >= HIDWORD(v58->Tcb.InitialStack)
        || (_ETHREAD *)v60->Tcb.Queue == v58 && v60->Tcb.WaitReason == 15 )
      {
        break;
      }
      v61 = Prcba;
      KiWakeQueueWaiter(Prcba, (_KQUEUE *)v58, (INT64)v55);
      if( !v62 )
        goto LABEL_92;
LABEL_96:
      _InterlockedAnd((volatile signed __int32 *)v58, 0xFFFFFF7F);
      v7 = (_KPRCB *)v70;
LABEL_99:
      v10 = (_KTIMER2 *)&Timer->gap0[8];
      if( v12 == (_KTIMER2 *)&Timer->gap0[8] )
      {
        CurrentThread = v69;
        goto LABEL_62;
      }
    }
    v61 = Prcba;
LABEL_92:
    v63 = *(_DWORD *)&v58->Tcb.gap0[4];
    *(_DWORD *)&v58->Tcb.gap0[4] = v63 + 1;
    v64 = (_KWAIT_BLOCK **)v58->Tcb.QuantumTarget;
    if( *v64 != (_KWAIT_BLOCK *)&v58->Tcb.SListFaultAddress )
LABEL_5:
      __fastfail(3u);
    v55->WaitListEntry.Flink = (_LIST_ENTRY *)&v58->Tcb.SListFaultAddress;
    v55->WaitListEntry.Blink = (_LIST_ENTRY *)v64;
    *v64 = v55;
    v58->Tcb.QuantumTarget = (unsigned __int64)v55;
    if( !v63 && (_QWORD *)*v59 != v59 )
      KiWakeOtherQueueWaiters(v61, (_KQUEUE *)v58);
    goto LABEL_96;
  }
LABEL_62:
  *(_QWORD *)&v10->gap0[8] = v10;
  *(_QWORD *)v10->gap0 = v10;
LABEL_26:
  v26 = (void(__fastcall *)(_KTIMER2 *, unsigned __int64))(KiWaitAlways ^ _byteswap_uint64((unsigned __int64)Timer ^ __ROL8__(KiWaitNever ^ (__int64)Timer->Callback, KiWaitNever)));
  if( v26 )
  {
    v33 = KiWaitAlways ^ _byteswap_uint64((unsigned __int64)Timer ^ __ROL8__(
                                                                      KiWaitNever ^ (__int64)Timer->CallbackContext,
                                                                      KiWaitNever));
    KiUpdateTimer2Flags(Timer, v8 | 0x10u, 0i64);
    if( v7->DeferredReadyListHead.Next )
      KiProcessThreadWaitList(v7, AdjustUnwait, 0i64, 2ui64);
    v34 = v73;
    v35 = v70;
    v36 = v70;
    v37 = ((*v73)++ & 0xF) + 1i64;
    v38 = &v34[4 * v37];
    *(_QWORD *)v38 = v26;
    v38[2] = KUSER_SHARED_DATA.TickCount.LowPart;
    *(_DWORD *)(v36 + 32412) = 0;
    KiResetGlobalDpcWatchdogProfiler(v36);
    *(_BYTE *)(v35 + 12586) = 1;
    v26(Timer, v33);
    *(_BYTE *)(v35 + 12586) = 0;
    v38[3] = KUSER_SHARED_DATA.TickCount.LowPart;
    _m_prefetchw(Timer);
    v39 = *(_DWORD *)Timer->gap0;
    do
    {
      v40 = v39;
      v39 = _InterlockedCompareExchange((volatile signed __int32 *)Timer, v39 & 0xFFFFEFFF, v39);
    }
    while( v40 != v39 );
    if( (v39 & 0x2F00) == 0x2000 )
      goto LABEL_29;
  }
  else
  {
    v27 = *(_DWORD *)Timer->gap0;
    v28 = v8 << 8;
    v29 = v28 | *(_DWORD *)Timer->gap0 & 0xFFFFF07F;
    v30 = _InterlockedCompareExchange((volatile signed __int32 *)Timer, v29, *(_DWORD *)Timer->gap0);
    if( v27 != v30 )
    {
      do
      {
        v65 = v30;
        v29 = v28 | v30 & 0xFFFFF07F;
        v30 = _InterlockedCompareExchange((volatile signed __int32 *)Timer, v29, v30);
      }
      while( v65 != v30 );
    }
    if( (v29 & 0x3F00) == 0x2000 )
LABEL_29:
      KiFinalizeTimer2Disablement(Timer);
  }
  if( (_DWORD)BugCheckParameter3 != CurrentThread->Tcb.WaitBlock[3].SpareLong )
    KeBugCheckEx(
      0xC7u,
      (PVOID)5,
      v26,
      (PVOID)(unsigned int)BugCheckParameter3,
      (PVOID)CurrentThread->Tcb.CombinedApcDisable);
}

Referenced by:

KiTimer2Expiration