VfDeadlockReleaseResource

VOID __fastcall VfDeadlockReleaseResource(
        VOID *Resource,
        _VI_DEADLOCK_RESOURCE_TYPE Type,
        _ETHREAD *Thread,
        VOID *Caller){
  _VI_DEADLOCK_THREAD *ThreadOwner; 
  UINT64 v6; 
  int v9; 
  _VI_DEADLOCK_RESOURCE_TYPE v10; 
  _VI_DEADLOCK_NODE *v11; 
  unsigned int v12; 
  VOID *v13; 
  __int64 v14; 
  volatile unsigned __int64 TickCountQuad; 
  _VI_DEADLOCK_RESOURCE *v16; 
  _VI_DEADLOCK_RESOURCE *Param3; 
  UINT64 v18; 
  __int16 v19; 
  _VI_DEADLOCK_THREAD *v20; 
  _VI_DEADLOCK_THREAD *v21; 
  _ETHREAD *v22; 
  _VI_DEADLOCK_NODE *CurrentSpinNode; 
  __int16 v24; 
  _DWORD *v25; 
  int v26; 
  _VI_DEADLOCK_NODE *CurrentOtherNode; 
  _VI_DEADLOCK_NODE *v28; 
  _VI_DEADLOCK_NODE *v29; 
  _VI_DEADLOCK_NODE *v30; 
  unsigned int NodeCount; 
  _QWORD *v32; 
  _QWORD *v33; 
  UINT8 OldIrql; 
  int v35; 
  PVOID Entry; 
  _ETHREAD *v37; 
  PVOID BackTrace[2]; 
  __int128 v39; 
  __int128 v40; 
  __int128 v41; 
  ThreadOwner = 0i64;
  v37 = Thread;
  v6 = Type;
  Entry = 0i64;
  memset((INT64)BackTrace, 0i64);
  v35 = 0;
  v9 = 0;
  if( !(unsigned int)ViDeadlockCanProceed(Resource, v10)
    || (unsigned int)ViIsThreadInsidePagingCodePaths()
    || *((_DWORD *)ViDeadlockGlobals + 8196)
    || *((int *)ViDeadlockGlobals + 8282) > 1024 )
  {
    return;
  }
  v11 = 0i64;
  v12 = RtlCaptureStackBackTrace(2ui64, 8ui64, BackTrace, 0i64);
  v13 = BackTrace[0];
  if( !v12 )
    v13 = Caller;
  BackTrace[0] = v13;
  v14 = 1i64;
  if( v12 )
    v14 = v12;
  if( (unsigned int)v14 < 8 )
    BackTrace[v14] = 0i64;
  OldIrql = ViRaiseIrqlToDpcLevel();
  ViDeadlockDetectionLock(1ui64);
  TickCountQuad = KUSER_SHARED_DATA.TickCountQuad;
  if( ViDeadlockDetectionEnabled )
  {
    v16 = ViDeadlockSearchResource(Resource, &Entry);
    Param3 = v16;
    if( !v16 )
    {
      v9 = 0;
      goto LABEL_59;
    }
    v18 = v16->Type;
    if( (_DWORD)v18 == (_DWORD)v6 )
      goto LABEL_17;
    if( (_DWORD)v18 == 7 )
    {
      if( (unsigned int)(v6 - 5) <= 1 )
      {
        Param3->Type = v6;
        LODWORD(v18) = v6;
        goto LABEL_17;
      }
    }
    else if( (_DWORD)v18 == 1 && (_DWORD)v6 == 2 )
    {
      if( *((_WORD *)Param3 + 3) > 1u )
        *((_WORD *)Param3 + 3) = 1;
      LODWORD(v18) = 1;
LABEL_17:
      v19 = *((_WORD *)Param3 + 3);
      if( v19 )
      {
        ThreadOwner = Param3->ThreadOwner;
        v22 = ThreadOwner->Thread;
        if( (unsigned int)(v18 - 5) <= 1 )
          CurrentSpinNode = ThreadOwner->CurrentSpinNode;
        else
          CurrentSpinNode = ThreadOwner->CurrentOtherNode;
        v24 = v19 - 1;
        *((_WORD *)Param3 + 3) = v24;
        if( !v24 )
        {
          v25 = ViDeadlockGlobals;
          Param3->ThreadOwner = 0i64;
          ++v25[8210];
          if( *((_VI_DEADLOCK_RESOURCE **)CurrentSpinNode + 7) == Param3 )
          {
            *((_DWORD *)CurrentSpinNode + 18) &= ~1u;
            v11 = CurrentSpinNode;
          }
          else
          {
            ++v25[8208];
            if( (ViDeadlockResourceTypeInfo[**((int **)CurrentSpinNode + 7)] & 4) == 0
              && (ViDeadlockResourceTypeInfo[Param3->Type] & 4) == 0 )
            {
              DbgPrintEx(0x5Du, 0, "Deadlock detection: Must release resources in reverse-order\n");
              DbgPrintEx(
                0x5Du,
                0,
                "Resource %p acquired before resource %p -- \nCurrent thread(%p) is trying to release %p first\n",
                Resource,
                *(const void **)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
                ThreadOwner,
                Resource);
              ViDeadlockPreprocessOptions(
                &dword_140C12D7C,
                "Releasing two locks in reverse order of their acquire.",
                0x1003ui64,
                (UINT64)Resource,
                *(_QWORD *)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
                (UINT64)ThreadOwner);
              VfReportIssueWithOptions(
                0xC4ui64,
                0x1003ui64,
                (UINT64)Resource,
                *(_QWORD *)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
                (UINT64)ThreadOwner,
                &dword_140C12D7C);
            }
            while( *((_VI_DEADLOCK_RESOURCE **)CurrentSpinNode + 7) != Param3 )
            {
              CurrentSpinNode = *(_VI_DEADLOCK_NODE **)CurrentSpinNode;
              if( !CurrentSpinNode )
                goto LABEL_42;
            }
            *((_DWORD *)CurrentSpinNode + 18) &= ~1u;
            v11 = CurrentSpinNode;
            v26 = *((_DWORD *)CurrentSpinNode + 18);
            if( (v26 & 4) == 0 )
            {
              ++*((_DWORD *)ViDeadlockGlobals + 8209);
              v26 = *((_DWORD *)CurrentSpinNode + 18);
            }
            *((_DWORD *)CurrentSpinNode + 18) = v26 | 4;
          }
LABEL_42:
          if( (unsigned int)(Param3->Type - 5) <= 1 )
          {
            v29 = ThreadOwner->CurrentSpinNode;
            if( v29 )
            {
              do
              {
                if( (*((_DWORD *)v29 + 18) & 1) != 0 && *((_VI_DEADLOCK_THREAD **)v29 + 8) == ThreadOwner )
                  break;
                v30 = *(_VI_DEADLOCK_NODE **)v29;
                ThreadOwner->CurrentSpinNode = *(_VI_DEADLOCK_NODE **)v29;
                v29 = v30;
              }
              while( v30 );
            }
          }
          else
          {
            CurrentOtherNode = ThreadOwner->CurrentOtherNode;
            if( CurrentOtherNode )
            {
              do
              {
                if( (*((_DWORD *)CurrentOtherNode + 18) & 1) != 0
                  && *((_VI_DEADLOCK_THREAD **)CurrentOtherNode + 8) == ThreadOwner )
                {
                  break;
                }
                v28 = *(_VI_DEADLOCK_NODE **)CurrentOtherNode;
                ThreadOwner->CurrentOtherNode = *(_VI_DEADLOCK_NODE **)CurrentOtherNode;
                CurrentOtherNode = v28;
              }
              while( v28 );
            }
          }
          if( v11 )
          {
            *((_QWORD *)v11 + 8) = 0i64;
            NodeCount = --ThreadOwner->NodeCount;
            if( v22 != v37 )
            {
              *((_DWORD *)v11 + 18) |= 4u;
              NodeCount = ThreadOwner->NodeCount;
            }
            if( !NodeCount )
            {
              v35 = 1;
              ViDeadlockRemoveThread(ThreadOwner, 0i64);
            }
          }
        }
      }
      else if( !*((_DWORD *)ViDeadlockGlobals + 8196) && *((int *)ViDeadlockGlobals + 8282) <= 1024 )
      {
        v20 = ViDeadlockSearchThread((_KTHREAD *)Thread);
        ViDeadlockPreprocessOptions(
          &byte_140C12D78,
          "Releasing lock 0x%p that is not owned by the current thread.",
          0x1007ui64,
          (UINT64)Resource,
          (UINT64)Param3,
          (UINT64)v20);
        v21 = ViDeadlockSearchThread((_KTHREAD *)Thread);
        VfReportIssueWithOptions(0xC4ui64, 0x1007ui64, (UINT64)Resource, (UINT64)Param3, (UINT64)v21, &byte_140C12D78);
      }
      goto LABEL_57;
    }
    ViDeadlockPreprocessOptions(
      &dword_140C12D74,
      "Releasing lock 0x%p using mismatched API for this lock type.",
      0x1009ui64,
      (UINT64)Resource,
      v18,
      v6);
    VfReportIssueWithOptions(0xC4ui64, 0x1009ui64, (UINT64)Resource, Param3->Type, v6, &dword_140C12D74);
LABEL_57:
    *(_OWORD *)Param3->LastReleaseTrace = *(_OWORD *)BackTrace;
    *(_OWORD *)&Param3->LastReleaseTrace[2] = v39;
    *(_OWORD *)&Param3->LastReleaseTrace[4] = v40;
    *(_OWORD *)&Param3->LastReleaseTrace[6] = v41;
    v9 = v35;
  }
LABEL_59:
  if( (signed __int64)(KUSER_SHARED_DATA.TickCountQuad - TickCountQuad) > *((_QWORD *)ViDeadlockGlobals + 1) )
    *((_QWORD *)ViDeadlockGlobals + 1) = KUSER_SHARED_DATA.TickCountQuad - TickCountQuad;
  ViDeadlockDetectionUnlock(1ui64);
  ViLowerIrql(OldIrql);
  v32 = Entry;
  if( Entry )
  {
    do
    {
      v33 = (_QWORD *)*v32;
      ViDeadlockFree(v32, 2);
      v32 = v33;
    }
    while( v33 );
  }
  if( v9 )
    ViDeadlockFree(ThreadOwner, 3);
}

Referenced by:

VerifierExReleaseFastMutex
VerifierExReleaseFastMutexUnsafe
VerifierKeReleaseInStackQueuedSpinLock
VerifierKeReleaseInStackQueuedSpinLockForDpc
VerifierKeReleaseInStackQueuedSpinLockFromDpcLevel
VerifierKeReleaseMutant
VerifierKeReleaseMutex
VerifierKeReleaseSpinLock
VerifierKeReleaseSpinLockFromDpcLevel