HalpTimerPerformanceCounterPowerChange

VOID **__fastcall HalpTimerPerformanceCounterPowerChange(INT64 BugCheckParameter3, VOID *a2, UINT64 a3, VOID *a4){
  VOID **result; 
  __int64(__fastcall **v5)(_QWORD); 
  __int64 v6; 
  int v7; 
  void *v8; 
  void *v9; 
  unsigned __int64 v10; 
  INT64 v11; 
  __int64 v12; 
  __int64 v13; 
  __int64 v14; 
  signed __int64 v15; 
  int v16; 
  unsigned __int64 v17; 
  __int64 v18; 
  __int64 v19; 
  unsigned __int64 v20; 
  signed __int64 v21; 
  __int64 v22; 
  __int64 v23; 
  __int64 v24; 
  PVOID v25; 
  UINT64 v26; 
  void *v27; 
  void *v28; 
  char *v29; 
  INT64 v30; 
  _QWORD *v31; 
  __int64 v32; 
  __int64 v33; 
  __int64 v34; 
  __int64 v35; 
  __int64 v36; 
  UINT64 v37; 
  signed __int64 v38; 
  void *v39; 
  UINT64 v40; 
  __int64 v41; 
  __int64 v42; 
  char *v43; 
  __int64 v44; 
  __int64 v45; 
  __int64 v46; 
  char *v47; 
  PVOID v48; 
  __int64 v49; 
  __int64 v50; 
  __int64 v51; 
  unsigned __int64 v52; 
  signed __int64 v53; 
  int v54; 
  unsigned __int64 v55; 
  __int64 v56; 
  __int64 v57; 
  unsigned __int64 v58; 
  signed __int64 v59; 
  __int64 v60; 
  __int64 v61; 
  __int64 v62; 
  INT64 v63; 
  UINT64 v64; 
  void *v65; 
  unsigned __int64 v66; 
  void *v67; 
  unsigned __int64 v68; 
  __int64 v69; 
  __int64 v70; 
  __int64 v71; 
  signed __int64 v72; 
  int v73; 
  unsigned __int64 v74; 
  unsigned __int64 v75; 
  signed __int64 v76; 
  __int64 v77; 
  __int64 v78; 
  __int64 v79; 
  PVOID v80; 
  char *v81; 
  void *v82; 
  void *v83; 
  int v84; 
  signed __int32 v85[8]; 
  void *retaddr; 

  result = &retaddr;
  v5 = (__int64(__fastcall **)(_QWORD))HalpTimerSavedPerformanceCounter;
  if( HalpTimerSavedPerformanceCounter )
  {
    if( (PVOID)BugCheckParameter3 == HalpTimerSavedPerformanceCounter && (_BYTE)a2 )
    {
      HalpTimerGetInternalData((_KDPC *)HalpTimerSavedPerformanceCounter, a2, (PVOID)a3, a4);
      v7 = v5[13](v6);
      if( v7 < 0 )
        KeBugCheckEx(0x5Cu, (PVOID)0x113, (PVOID)0xF, v5, (PVOID)v7);
      if( HalpTimerDelayedQueryHardwareCount )
      {
        *(_QWORD *)(HalpPerformanceCounter + 112) = HalpTimerDelayedQueryHardwareCount;
        HalpTimerDelayedQueryHardwareCount = 0i64;
      }
      v11 = HalpPerformanceCounter;
      if( *(_DWORD *)(HalpPerformanceCounter + 220) == 64 )
      {
        HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, v8, v9, (PVOID)v10);
        v24 = (*(__int64(__fastcall **)(__int64))(v11 + 112))(v23);
        v12 = *(_QWORD *)(v11 + 208);
        v21 = v24;
      }
      else
      {
        do
        {
          v12 = *(_QWORD *)(v11 + 208);
          do
          {
            v13 = *(_QWORD *)(v11 + 200);
            HalpTimerGetInternalData((_KDPC *)v11, v8, v9, (PVOID)v10);
            v10 = (*(__int64(__fastcall **)(__int64))(v11 + 112))(v14);
            _InterlockedOr(v85, 0);
            v15 = *(_QWORD *)(v11 + 200);
          }
          while( v13 != v15 );
        }
        while( v12 != *(_QWORD *)(v11 + 208) );
        v16 = *(_DWORD *)(v11 + 220);
        v17 = v13 ^ v10;
        if( _bittest64((const __int64 *)&v17, (unsigned __int8)(v16 - 1)) )
        {
          v18 = 1i64;
          if( v16 == 64 )
            v19 = -1i64;
          else
            v19 = (1i64 << v16) - 1;
          if( v16 != 64 )
            v18 = 1i64 << v16;
          v20 = v13 & v19;
          v21 = v10 | v13 ^ v20;
          if( v10 < v20 )
            v21 += v18;
          _InterlockedCompareExchange64((volatile signed __int64 *)(v11 + 200), v21, v15);
        }
        else
        {
          if( v16 == 64 )
            v22 = -1i64;
          else
            v22 = (1i64 << v16) - 1;
          v21 = v10 | v13 & ~v22;
        }
      }
      v25 = HalpTimerSavedPerformanceCounter;
      v26 = HalpTimerScaleCounter(
              v12 + v21,
              *(_QWORD *)(HalpPerformanceCounter + 192),
              *((_QWORD *)HalpTimerSavedPerformanceCounter + 24));
      v29 = (char *)*((_QWORD *)v25 + 2);
      if( v26 >= (unsigned __int64)v29 )
        v29 = (char *)v26;
      result = (VOID **)HalpTimerCalibratePerformanceCounter((INT64)v5, v29, v27, v28);
      if( (int)result < 0 )
        KeBugCheckEx(0x5Cu, (PVOID)0x113, (PVOID)0x26, v5, (PVOID)(int)result);
      HalpTimerSavedPerformanceCounter = 0i64;
      HalpPerformanceCounter = (INT64)v5;
    }
  }
  else
  {
    v30 = HalpPerformanceCounter;
    if( BugCheckParameter3 == HalpPerformanceCounter && !(_BYTE)a2 )
    {
      v31 = HalpAlwaysOnCounter;
      HalpTimerSavedPerformanceCounter = (PVOID)HalpPerformanceCounter;
      if( !HalpAlwaysOnCounter )
        KeBugCheckEx(
          (_DWORD)HalpAlwaysOnCounter + 92,
          (PVOID)0x113,
          (PVOID)(unsigned int)((_DWORD)HalpAlwaysOnCounter + 34),
          (PVOID)BugCheckParameter3,
          0i64);
      v32 = -1i64;
      v33 = 1i64;
      if( *(_DWORD *)(HalpPerformanceCounter + 220) == 64 )
      {
        HalpTimerGetInternalData((_KDPC *)HalpPerformanceCounter, a2, (PVOID)a3, a4);
        v46 = (*(__int64(__fastcall **)(__int64))(v30 + 112))(v45);
        v34 = *(_QWORD *)(v30 + 208);
        v43 = (char *)v46;
      }
      else
      {
        do
        {
          v34 = *(_QWORD *)(v30 + 208);
          do
          {
            v35 = *(_QWORD *)(v30 + 200);
            HalpTimerGetInternalData((_KDPC *)v30, a2, (PVOID)a3, a4);
            v37 = (*(__int64(__fastcall **)(__int64))(v30 + 112))(v36);
            _InterlockedOr(v85, 0);
            v38 = *(_QWORD *)(v30 + 200);
          }
          while( v35 != v38 );
        }
        while( v34 != *(_QWORD *)(v30 + 208) );
        v39 = (void *)*(unsigned int *)(v30 + 220);
        v40 = v35 ^ v37;
        if( _bittest64((const __int64 *)&v40, (unsigned __int8)((_BYTE)v39 - 1)) )
        {
          if( (_DWORD)v39 == 64 )
            v41 = -1i64;
          else
            v41 = (1i64 << (char)v39) - 1;
          v42 = 1i64;
          if( (_DWORD)v39 != 64 )
            v42 = 1i64 << (char)v39;
          a3 = v35 & v41;
          v43 = (char *)(v37 | v35 ^ a3);
          if( v37 < a3 )
            v43 += v42;
          _InterlockedCompareExchange64((volatile signed __int64 *)(v30 + 200), (signed __int64)v43, v38);
        }
        else
        {
          if( (_DWORD)v39 == 64 )
            v44 = -1i64;
          else
            v44 = (1i64 << (char)v39) - 1;
          v43 = (char *)(v37 | v35 & ~v44);
        }
      }
      v47 = &v43[v34];
      v48 = HalpAlwaysOnCounter;
      *(_QWORD *)(HalpPerformanceCounter + 16) = v47;
      if( *((_DWORD *)v48 + 55) == 64 )
      {
        HalpTimerGetInternalData((_KDPC *)v48, v43, (PVOID)a3, v39);
        v62 = (*((__int64(__fastcall **)(__int64))v48 + 14))(v61);
        v49 = *((_QWORD *)v48 + 26);
        v59 = v62;
      }
      else
      {
        do
        {
          v49 = *((_QWORD *)v48 + 26);
          do
          {
            v50 = *((_QWORD *)v48 + 25);
            HalpTimerGetInternalData((_KDPC *)v48, v43, (PVOID)a3, v39);
            v52 = (*((__int64(__fastcall **)(__int64))v48 + 14))(v51);
            _InterlockedOr(v85, 0);
            v53 = *((_QWORD *)v48 + 25);
          }
          while( v50 != v53 );
        }
        while( v49 != *((_QWORD *)v48 + 26) );
        v54 = *((_DWORD *)v48 + 55);
        v55 = v50 ^ v52;
        if( _bittest64((const __int64 *)&v55, (unsigned __int8)(v54 - 1)) )
        {
          if( v54 == 64 )
            v56 = -1i64;
          else
            v56 = (1i64 << v54) - 1;
          v57 = 1i64;
          if( v54 != 64 )
            v57 = 1i64 << v54;
          v58 = v50 & v56;
          v59 = v52 | v50 ^ v58;
          if( v52 < v58 )
            v59 += v57;
          _InterlockedCompareExchange64((volatile signed __int64 *)v48 + 25, v59, v53);
        }
        else
        {
          if( v54 == 64 )
            v60 = -1i64;
          else
            v60 = (1i64 << v54) - 1;
          v59 = v52 | v50 & ~v60;
        }
      }
      v63 = HalpPerformanceCounter;
      v64 = HalpTimerScaleCounter(
              v49 + v59,
              *((_QWORD *)HalpAlwaysOnCounter + 24),
              *(_QWORD *)(HalpPerformanceCounter + 192));
      v67 = (void *)(v64 - (_QWORD)v47);
      v68 = (unsigned __int64)&v47[-v64];
      if( (unsigned __int64)v47 <= v64 )
        v68 = v64 - (_QWORD)v47;
      if( v68 > HalpTimerMaximumAllowableDrift )
      {
        ++HalpTimerDriftReadjustmentCount;
        if( *(_DWORD *)(v63 + 220) == 64 )
        {
          HalpTimerGetInternalData((_KDPC *)v63, v67, v65, (PVOID)v66);
          v79 = (*(__int64(__fastcall **)(__int64))(v63 + 112))(v78);
          v69 = *(_QWORD *)(v63 + 208);
          v76 = v79;
        }
        else
        {
          do
          {
            v69 = *(_QWORD *)(v63 + 208);
            do
            {
              v70 = *(_QWORD *)(v63 + 200);
              HalpTimerGetInternalData((_KDPC *)v63, v67, v65, (PVOID)v66);
              v66 = (*(__int64(__fastcall **)(__int64))(v63 + 112))(v71);
              _InterlockedOr(v85, 0);
              v72 = *(_QWORD *)(v63 + 200);
            }
            while( v70 != v72 );
          }
          while( v69 != *(_QWORD *)(v63 + 208) );
          v73 = *(_DWORD *)(v63 + 220);
          v74 = v70 ^ v66;
          if( _bittest64((const __int64 *)&v74, (unsigned __int8)(v73 - 1)) )
          {
            if( v73 != 64 )
              v32 = (1i64 << v73) - 1;
            if( v73 != 64 )
              v33 = 1i64 << v73;
            v75 = v70 & v32;
            v76 = v66 | v70 ^ v75;
            if( v66 < v75 )
              v76 += v33;
            _InterlockedCompareExchange64((volatile signed __int64 *)(v63 + 200), v76, v72);
          }
          else
          {
            if( v73 == 64 )
              v77 = -1i64;
            else
              v77 = (1i64 << v73) - 1;
            v76 = v66 | v70 & ~v77;
          }
        }
        v80 = HalpAlwaysOnCounter;
        v81 = (char *)HalpTimerScaleCounter(
                        v69 + v76,
                        *(_QWORD *)(HalpPerformanceCounter + 192),
                        *((_QWORD *)HalpAlwaysOnCounter + 24));
        v84 = HalpTimerCalibratePerformanceCounter((INT64)v80, v81, v82, v83);
        if( v84 < 0 )
          KeBugCheckEx(0x5Cu, (PVOID)0x113, (PVOID)0x26, HalpAlwaysOnCounter, (PVOID)v84);
      }
      HalpTimerDelayedQueryHardwareCount = v31[14];
      v31[14] = HalpTimerDelayedQueryCounter;
      HalpTimerSavedPerformanceCounter = (PVOID)HalpPerformanceCounter;
      result = (VOID **)HalpAlwaysOnCounter;
      HalpPerformanceCounter = (INT64)HalpAlwaysOnCounter;
    }
  }
  return result;
}

Referenced by:

HalpTimerPowerChange