VfDeadlockReleaseResource

VOID __stdcall 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 *Param4; 
  ULONG_PTR v21; 
  _ETHREAD *v22; 
  _VI_DEADLOCK_NODE *CurrentSpinNode; 
  __int16 v24; 
  _DWORD *v25; 
  union {$ACDF71180F6620BE0295814E0676F670 __s0;unsigned int Whole;} v26; 
  _VI_DEADLOCK_NODE *CurrentOtherNode; 
  _VI_DEADLOCK_NODE *v28; 
  _VI_DEADLOCK_NODE *v29; 
  _VI_DEADLOCK_NODE *Parent; 
  unsigned int NodeCount; 
  _QWORD *v32; 
  _QWORD *v33; 
  UINT64 a7; 
  UINT64 a7a; 
  UINT8 OldIrql; 
  int v37; 
  VOID *NodesToFree; 
  _ETHREAD *v39; 
  VOID *BackTrace[8]; 

  ThreadOwner = 0i64;
  v39 = Thread;
  v6 = Type;
  NodesToFree = 0i64;
  memset(BackTrace, 0i64, sizeof(BackTrace));
  v37 = 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, &NodesToFree);
    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( CurrentSpinNode->Root == Param3 )
          {
            CurrentSpinNode->u1.Whole &= ~1u;
            v11 = CurrentSpinNode;
          }
          else
          {
            ++v25[8208];
            if( (ViDeadlockResourceTypeInfo[CurrentSpinNode->Root->Type] & 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,
                CurrentSpinNode->Root->ResourceAddress,
                ThreadOwner,
                Resource);
              ViDeadlockPreprocessOptions(
                &qword_140C12D7C,
                (CHAR *)"Releasing two locks in reverse order of their acquire.",
                0x1003ui64,
                (UINT64)Resource,
                (UINT64)CurrentSpinNode->Root->ResourceAddress,
                (UINT64)ThreadOwner,
                a7a);
              VfReportIssueWithOptions(
                0xC4ui64,
                0x1003u,
                (ULONG_PTR)Resource,
                (ULONG_PTR)CurrentSpinNode->Root->ResourceAddress,
                (ULONG_PTR)ThreadOwner,
                &qword_140C12D7C);
            }
            while( CurrentSpinNode->Root != Param3 )
            {
              CurrentSpinNode = CurrentSpinNode->Parent;
              if( !CurrentSpinNode )
                goto LABEL_42;
            }
            CurrentSpinNode->u1.Whole &= ~1u;
            v11 = CurrentSpinNode;
            v26.0 = ($ACDF71180F6620BE0295814E0676F670)CurrentSpinNode->u1;
            if( (*(_BYTE *)&v26.0 & 4) == 0 )
            {
              ++*((_DWORD *)ViDeadlockGlobals + 8209);
              v26.0 = ($ACDF71180F6620BE0295814E0676F670)CurrentSpinNode->u1;
            }
            CurrentSpinNode->u1.Whole = v26.Whole | 4;
          }
LABEL_42:
          if( (unsigned int)(Param3->Type - 5) <= 1 )
          {
            v29 = ThreadOwner->CurrentSpinNode;
            if( v29 )
            {
              do
              {
                if( (v29->u1.Whole & 1) != 0 && v29->ThreadEntry == ThreadOwner )
                  break;
                Parent = v29->Parent;
                ThreadOwner->CurrentSpinNode = v29->Parent;
                v29 = Parent;
              }
              while( Parent );
            }
          }
          else
          {
            CurrentOtherNode = ThreadOwner->CurrentOtherNode;
            if( CurrentOtherNode )
            {
              do
              {
                if( (CurrentOtherNode->u1.Whole & 1) != 0 && CurrentOtherNode->ThreadEntry == ThreadOwner )
                  break;
                v28 = CurrentOtherNode->Parent;
                ThreadOwner->CurrentOtherNode = CurrentOtherNode->Parent;
                CurrentOtherNode = v28;
              }
              while( v28 );
            }
          }
          if( v11 )
          {
            v11->ThreadEntry = 0i64;
            NodeCount = --ThreadOwner->NodeCount;
            if( v22 != v39 )
            {
              v11->u1.Whole |= 4u;
              NodeCount = ThreadOwner->NodeCount;
            }
            if( !NodeCount )
            {
              v37 = 1;
              ViDeadlockRemoveThread(ThreadOwner, 0i64);
            }
          }
        }
      }
      else if( !*((_DWORD *)ViDeadlockGlobals + 8196) && *((int *)ViDeadlockGlobals + 8282) <= 1024 )
      {
        Param4 = ViDeadlockSearchThread(&Thread->Tcb);
        ViDeadlockPreprocessOptions(
          &unk_140C12D78,
          (CHAR *)"Releasing lock 0x%p that is not owned by the current thread.",
          0x1007ui64,
          (UINT64)Resource,
          (UINT64)Param3,
          (UINT64)Param4,
          a7);
        v21 = (unsigned int)ViDeadlockSearchThread(&Thread->Tcb);
        VfReportIssueWithOptions(0xC4ui64, 0x1007u, (ULONG_PTR)Resource, (ULONG_PTR)Param3, v21, &unk_140C12D78);
      }
      goto LABEL_57;
    }
    ViDeadlockPreprocessOptions(
      (UINT64 *)((char *)&qword_140C12D70 + 4),
      (CHAR *)"Releasing lock 0x%p using mismatched API for this lock type.",
      0x1009ui64,
      (UINT64)Resource,
      v18,
      v6,
      a7);
    VfReportIssueWithOptions(
      0xC4ui64,
      0x1009u,
      (ULONG_PTR)Resource,
      Param3->Type,
      v6,
      (UINT64 *)((char *)&qword_140C12D70 + 4));
LABEL_57:
    *(_OWORD *)Param3->LastReleaseTrace = *(_OWORD *)BackTrace;
    *(_OWORD *)&Param3->LastReleaseTrace[2] = *(_OWORD *)&BackTrace[2];
    *(_OWORD *)&Param3->LastReleaseTrace[4] = *(_OWORD *)&BackTrace[4];
    *(_OWORD *)&Param3->LastReleaseTrace[6] = *(_OWORD *)&BackTrace[6];
    v9 = v37;
  }
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 = NodesToFree;
  if( NodesToFree )
  {
    do
    {
      v33 = (_QWORD *)*v32;
      ViDeadlockFree(v32, ViDeadlockNode);
      v32 = v33;
    }
    while( v33 );
  }
  if( v9 )
    ViDeadlockFree(ThreadOwner, ViDeadlockThread);
}

Referenced by:

VerifierExReleaseFastMutex
VerifierExReleaseFastMutexUnsafe
VerifierKeReleaseInStackQueuedSpinLock
VerifierKeReleaseInStackQueuedSpinLockForDpc
VerifierKeReleaseInStackQueuedSpinLockFromDpcLevel
VerifierKeReleaseMutant
VerifierKeReleaseMutex
VerifierKeReleaseSpinLock
VerifierKeReleaseSpinLockFromDpcLevel