VfDeadlockAcquireResource

VOID __fastcall VfDeadlockAcquireResource(VOID *Resource, INT64 a2, _ETHREAD *a3, UINT64 a4, INT64 a5){
  UINT64 Param4; 
  _VI_DEADLOCK_RESOURCE_TYPE v8; 
  VOID *v9; 
  _VI_DEADLOCK_THREAD *v10; 
  UINT16 v11; 
  unsigned int v12; 
  volatile unsigned __int64 TickCountQuad; 
  _VI_DEADLOCK_THREAD *v14; 
  VOID *v15; 
  int v16; 
  _VI_DEADLOCK_RESOURCE *v17; 
  _VI_DEADLOCK_THREAD *v18; 
  _VI_DEADLOCK_RESOURCE *v19; 
  UINT64 Type; 
  _VI_DEADLOCK_NODE *CurrentSpinNode; 
  _VI_DEADLOCK_THREAD *ThreadOwner; 
  unsigned __int16 v23; 
  UINT64 v24; 
  _LIST_ENTRY *Flink; 
  _VI_DEADLOCK_NODE *p_Blink; 
  _LIST_ENTRY *v27; 
  int v28; 
  _QWORD *v29; 
  _QWORD *v30; 
  _LIST_ENTRY *p_ResourceList; 
  _LIST_ENTRY *v32; 
  UINT64 v33; 
  _LIST_ENTRY *p_SiblingsList; 
  int v35; 
  _LIST_ENTRY *p_ChildrenList; 
  _LIST_ENTRY *v37; 
  _LIST_ENTRY *v38; 
  _LIST_ENTRY *v39; 
  $40597CAD8088CB40007EECA86A191ECD *v40; 
  _VI_DEADLOCK_NODE *Parent; 
  _VI_DEADLOCK_RESOURCE *Root; 
  UINT64 a7; 
  VOID *ReservedThread; 
  VOID *ReservedResource; 
  unsigned int TryNode; 
  VOID *NodesToFree; 
  int v48; 
  VOID *v49; 
  int v50; 
  VOID *v51; 
  VOID *Object; 
  VOID *Caller; 
  VOID *BackTrace[8]; 

  Param4 = (int)a2;
  TryNode = a4;
  Caller = (VOID *)a5;
  memset(BackTrace, 0i64, sizeof(BackTrace));
  v48 = 0;
  v9 = 0i64;
  LODWORD(a7) = 0;
  Object = 0i64;
  NodesToFree = 0i64;
  if( (_DWORD)Param4 == 8
    && (!VfWin32kDllBase
     || VfWin32kDllBase > (unsigned __int64)a5
     || VfWin32kDllBase + (unsigned __int64)(unsigned int)VfWin32kSizeOfImage <= a5)
    || !(unsigned int)ViDeadlockCanProceed(Resource, v8)
    || (unsigned int)ViIsThreadInsidePagingCodePaths()
    || *((_DWORD *)ViDeadlockGlobals + 8196)
    || *((int *)ViDeadlockGlobals + 8282) > 1024 )
  {
    return;
  }
  v49 = 0i64;
  v10 = 0i64;
  v50 = ViDeadlockResourceTypeInfo[Param4];
  ReservedThread = ViDeadlockAllocate(ViDeadlockThread);
  v51 = ViDeadlockAllocate(ViDeadlockNode);
  ReservedResource = ViDeadlockAllocate(ViDeadlockResource);
  v11 = RtlCaptureStackBackTrace(2ui64, 8ui64, BackTrace, 0i64);
  v12 = v11;
  if( !v11 )
  {
    BackTrace[0] = (VOID *)a5;
    v12 = 1;
  }
  if( v12 < 8 )
    BackTrace[v12] = 0i64;
  BYTE4(a7) = ViRaiseIrqlToDpcLevel();
  ViDeadlockDetectionLock(1ui64);
  TickCountQuad = KUSER_SHARED_DATA.TickCountQuad;
  if( !ViDeadlockDetectionEnabled || (v49 = v51, v51 = 0i64, !v49) )
  {
LABEL_50:
    v15 = ReservedResource;
    goto LABEL_51;
  }
  v10 = ViDeadlockSearchThread(&a3->Tcb);
  if( !v10 )
  {
    v14 = ViDeadlockAddThread(&a3->Tcb, ReservedThread);
    ReservedThread = 0i64;
    v10 = v14;
    if( !v14 )
    {
      v15 = ReservedResource;
      v16 = 0;
      goto LABEL_53;
    }
    LODWORD(v9) = 1;
  }
  if( (_DWORD)Param4 != 8 )
  {
    v17 = ViDeadlockSearchResource(Resource, &NodesToFree);
    v18 = 0i64;
    v19 = v17;
    if( !v17 )
    {
      v15 = ReservedResource;
      if( !(unsigned int)ViDeadlockAddResource(
                            Resource,
                            (_VI_DEADLOCK_RESOURCE_TYPE)Param4,
                            ReservedResource,
                            BackTrace,
                            &Object,
                            &NodesToFree) )
      {
        if( (_DWORD)v9 )
        {
          v16 = 1;
          ViDeadlockRemoveThread(v10, 0i64);
          goto LABEL_52;
        }
LABEL_51:
        v16 = 0;
        goto LABEL_52;
      }
      ReservedResource = 0i64;
      v19 = ViDeadlockSearchResource(Resource, &NodesToFree);
      v18 = 0i64;
    }
    Type = v19->Type;
    if( (_DWORD)Type != (_DWORD)Param4 )
    {
      if( ((unsigned int)(Param4 - 3) > 1 || (unsigned int)(Type - 3) > 1)
        && ((_DWORD)Type != 7 || (unsigned int)(Param4 - 5) > 1) )
      {
        ViDeadlockPreprocessOptions(
          (UINT64 *)((char *)&qword_140C12D84 + 4),
          (CHAR *)"Acquiring lock 0x%p using mismatched API for this lock type.",
          0x1008ui64,
          (UINT64)Resource,
          Type,
          Param4,
          a7);
        VfReportIssueWithOptions(
          0xC4ui64,
          0x1008u,
          (ULONG_PTR)Resource,
          v19->Type,
          Param4,
          (UINT64 *)((char *)&qword_140C12D84 + 4));
        goto LABEL_35;
      }
      v19->Type = Param4;
    }
    if( (unsigned int)(Param4 - 5) <= 1 )
      CurrentSpinNode = v10->CurrentSpinNode;
    else
      CurrentSpinNode = v10->CurrentOtherNode;
    ThreadOwner = v19->ThreadOwner;
    if( ThreadOwner && ThreadOwner != v10 )
      *((_WORD *)v19 + 3) = 0;
    v23 = *((_WORD *)v19 + 3) + 1;
    v19->ThreadOwner = v10;
    *((_WORD *)v19 + 3) = v23;
    if( CurrentSpinNode )
    {
      if( v23 > 1u )
      {
        if( (v50 & 1) != 0 )
          goto LABEL_20;
        ViDeadlockPreprocessOptions(
          &unk_140C12D8C,
          (CHAR *)"Lock 0x%p doesn't support recursive acquire.",
          0x1000ui64,
          (UINT64)Resource,
          (UINT64)v19,
          (UINT64)v10,
          a7);
        VfReportIssueWithOptions(0xC4ui64, 0x1000u, (ULONG_PTR)Resource, (ULONG_PTR)v19, (ULONG_PTR)v10, &unk_140C12D8C);
LABEL_35:
        v15 = ReservedResource;
        v16 = a7;
        goto LABEL_52;
      }
      v24 = TryNode;
      Flink = CurrentSpinNode->ChildrenList.Flink;
      if( Flink != &CurrentSpinNode->ChildrenList )
      {
        while( 1 )
        {
          p_Blink = (_VI_DEADLOCK_NODE *)&Flink[-2].Blink;
          if( (unsigned int)ViDeadlockSimilarNode(Resource, v24, (_VI_DEADLOCK_NODE *)&Flink[-2].Blink) )
            break;
          if( Flink == v27 )
            goto LABEL_47;
        }
        ViDeadlockCheckDuplicatesAmongChildren((INT64)CurrentSpinNode, (INT64)p_Blink, (INT64 **)&NodesToFree);
        goto LABEL_85;
      }
LABEL_47:
      if( *((_WORD *)v19 + 2) )
      {
        if( !(_DWORD)v24 )
        {
          v28 = ViDeadlockAnalyze(Resource, CurrentSpinNode, 1ui64, 0i64, Caller);
          v18 = 0i64;
          if( v28 )
            goto LABEL_50;
        }
      }
    }
    else
    {
      p_ResourceList = &v19->ResourceList;
      v32 = v19->ResourceList.Flink;
      if( v32 != &v19->ResourceList )
      {
        v33 = TryNode;
        while( 1 )
        {
          p_Blink = (_VI_DEADLOCK_NODE *)&v32[-3].Blink;
          v32 = v32->Flink;
          if( (_VI_DEADLOCK_THREAD *)p_Blink->Parent == v18 )
          {
            if( (unsigned int)ViDeadlockSimilarNode(Resource, v33, p_Blink) )
              break;
          }
          if( v32 == p_ResourceList )
            goto LABEL_76;
        }
        ViDeadlockCheckDuplicatesAmongRoots((INT64)p_Blink, (INT64 **)&NodesToFree);
        goto LABEL_85;
      }
LABEL_76:
      v48 = 1;
    }
    p_Blink = (_VI_DEADLOCK_NODE *)v49;
    v49 = v18;
    *(_QWORD *)&p_Blink->u1.0 = 0i64;
    p_Blink->ThreadEntry = v18;
    p_SiblingsList = &p_Blink->SiblingsList;
    p_Blink->StackTrace[0] = v18;
    p_Blink->ParentStackTrace[0] = v18;
    p_Blink->Parent = CurrentSpinNode;
    p_Blink->Root = v19;
    v35 = *((_DWORD *)ViDeadlockGlobals + 8201);
    p_Blink->ChildrenList.Blink = &p_Blink->ChildrenList;
    p_Blink->ChildrenList.Flink = &p_Blink->ChildrenList;
    p_Blink->SiblingsList.Blink = &p_Blink->SiblingsList;
    p_Blink->SiblingsList.Flink = &p_Blink->SiblingsList;
    p_Blink->u1.Whole = 2 * (TryNode & 1 | (4 * v35));
    if( v48 == (_DWORD)v18 )
    {
      p_ChildrenList = &CurrentSpinNode->ChildrenList;
      v37 = CurrentSpinNode->ChildrenList.Flink;
      if( v37->Blink != &CurrentSpinNode->ChildrenList )
        goto LABEL_81;
      p_SiblingsList->Flink = v37;
      p_Blink->SiblingsList.Blink = p_ChildrenList;
      v37->Blink = p_SiblingsList;
      p_ChildrenList->Flink = p_SiblingsList;
      ViDeadlockUpdateChildrenCount(CurrentSpinNode, 1i64);
    }
    v38 = &v19->ResourceList;
    v39 = v19->ResourceList.Flink;
    v40 = &p_Blink->40;
    if( v39->Blink == &v19->ResourceList )
    {
      v40->ResourceList.Flink = v39;
      p_Blink->ResourceList.Blink = v38;
      v39->Blink = &v40->ResourceList;
      v38->Flink = &v40->ResourceList;
      ++*((_WORD *)v19 + 2);
      if( (unsigned __int16)*((_DWORD *)v19 + 1) > 0xFFF0u )
        ViDeadlockState |= 0x20u;
LABEL_85:
      if( p_Blink )
      {
        p_Blink->u1.Whole |= 1u;
        p_Blink->ThreadEntry = v10;
        if( (unsigned int)(Param4 - 5) <= 1 )
          v10->CurrentSpinNode = p_Blink;
        else
          v10->CurrentOtherNode = p_Blink;
        ++v10->NodeCount;
        Parent = p_Blink->Parent;
        if( p_Blink->Parent )
        {
          *(_OWORD *)p_Blink->ParentStackTrace = *(_OWORD *)Parent->StackTrace;
          *(_OWORD *)&p_Blink->ParentStackTrace[2] = *(_OWORD *)&Parent->StackTrace[2];
          *(_OWORD *)&p_Blink->ParentStackTrace[4] = *(_OWORD *)&Parent->StackTrace[4];
          *(_OWORD *)&p_Blink->ParentStackTrace[6] = *(_OWORD *)&Parent->StackTrace[6];
        }
        Root = p_Blink->Root;
        *(_OWORD *)p_Blink->StackTrace = *(_OWORD *)BackTrace;
        *(_OWORD *)&p_Blink->StackTrace[2] = *(_OWORD *)&BackTrace[2];
        *(_OWORD *)&p_Blink->StackTrace[4] = *(_OWORD *)&BackTrace[4];
        *(_OWORD *)&p_Blink->StackTrace[6] = *(_OWORD *)&BackTrace[6];
        *(_OWORD *)Root->LastAcquireTrace = *(_OWORD *)p_Blink->StackTrace;
        *(_OWORD *)&Root->LastAcquireTrace[2] = *(_OWORD *)&p_Blink->StackTrace[2];
        *(_OWORD *)&Root->LastAcquireTrace[4] = *(_OWORD *)&p_Blink->StackTrace[4];
        *(_OWORD *)&Root->LastAcquireTrace[6] = *(_OWORD *)&p_Blink->StackTrace[6];
      }
      goto LABEL_20;
    }
LABEL_81:
    __fastfail(3u);
  }
  v10->ThreadUsesEresources = 1;
LABEL_20:
  v15 = ReservedResource;
  v16 = 0;
LABEL_52:
  v9 = ReservedThread;
LABEL_53:
  if( (signed __int64)(KUSER_SHARED_DATA.TickCountQuad - TickCountQuad) > *(_QWORD *)ViDeadlockGlobals )
    *(_QWORD *)ViDeadlockGlobals = KUSER_SHARED_DATA.TickCountQuad - TickCountQuad;
  ViDeadlockDetectionUnlock(1ui64);
  ViLowerIrql(BYTE4(a7));
  v29 = NodesToFree;
  if( NodesToFree )
  {
    do
    {
      v30 = (_QWORD *)*v29;
      ViDeadlockFree(v29, ViDeadlockNode);
      v29 = v30;
    }
    while( v30 );
  }
  if( Object )
    ViDeadlockFree(Object, ViDeadlockResource);
  if( v16 )
    ViDeadlockFree(v10, ViDeadlockThread);
  if( v49 )
    ViDeadlockFree(v49, ViDeadlockNode);
  if( v15 )
    ViDeadlockFree(v15, ViDeadlockResource);
  if( v51 )
    ViDeadlockFree(v51, ViDeadlockNode);
  if( v9 )
    ViDeadlockFree(v9, ViDeadlockThread);
}

Referenced by:

VerifierExAcquireFastMutex
VerifierExAcquireFastMutexUnsafe
VerifierExAcquireResourceExclusiveLite
VerifierExAcquireResourceSharedLite
VerifierExAcquireSharedStarveExclusive
VerifierExAcquireSharedWaitForExclusive
VerifierExEnterCriticalRegionAndAcquireResourceExclusive
VerifierExEnterCriticalRegionAndAcquireResourceShared
VerifierExEnterPriorityRegionAndAcquireResourceExclusive
VerifierExEnterPriorityRegionAndAcquireResourceShared
VerifierExTryToAcquireFastMutex
VerifierKeAcquireInStackQueuedSpinLock
VerifierKeAcquireInStackQueuedSpinLockAtDpcLevel
VerifierKeAcquireInStackQueuedSpinLockForDpc
VerifierKeAcquireInStackQueuedSpinLockRaiseToSynch
VerifierKeAcquireSpinLockAtDpcLevel
VerifierKeAcquireSpinLockRaiseToDpc
VerifierKeInitializeMutant
VerifierKeTryToAcquireSpinLockAtDpcLevel
ViKeObjectAcquired