FsRtlpRequestExclusiveOplock

VOID __stdcall FsRtlpRequestExclusiveOplock(
        _NONOPAQUE_OPLOCK **Oplock,
        _IO_STACK_LOCATION *IrpSp,
        _IRP *Irp,
        UINT64 OpenCount,
        UINT64 FsctrlFlags,
        UINT64 NextOplockState,
        UINT64 LowerOplockLevel){
  unsigned int v7; 
  _IO_STACK_LOCATION *v9; 
  _NONOPAQUE_OPLOCK *v11; 
  INT64 v12; 
  int v13; 
  char v14; 
  _RH_OP_CONTEXT *v15; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *Blink; 
  int v18; 
  _CCHAR v19; 
  _WAITING_IRP *i; 
  _WAITING_IRP *v21; 
  _RH_OP_CONTEXT *v22; 
  _LIST_ENTRY *v23; 
  _LIST_ENTRY *v24; 
  char v25; 
  unsigned int OplockState; 
  char v27; 
  int v28; 
  _ETHREAD *CurrentThread; 
  INT64 v30; 
  INT64 v31; 
  int v32; 
  INT64 v33; 
  INT64 v34; 
  char v35; 
  __int64 v36; 
  __int64 MasterIrp; 
  _LIST_ENTRY *p_IrpOplocksRH; 
  _LIST_ENTRY *m; 
  char v40; 
  __int64 n; 
  __int64 *v42; 
  _BOOL4 v43; 
  VOID *v44; 
  _LIST_ENTRY *p_IrpOplocksR; 
  _LIST_ENTRY *j; 
  char v47; 
  _LIST_ENTRY *k; 
  _LIST_ENTRY **p_Flink; 
  _RH_OP_CONTEXT **v50; 
  INT64 v51; 
  UINT64 AccessMode; 
  INT64 a3; 
  __int64 v54; 
  _NONOPAQUE_OPLOCK *v55; 
  _IRP *IrpExclusiveOplock; 
  __int64 v57; 
  _LIST_ENTRY *v58; 
  _IO_STACK_LOCATION *CurrentStackLocation; 
  unsigned int v61; 

  v61 = OpenCount;
  v7 = OpenCount;
  v9 = IrpSp;
  a3 = 0i64;
  v11 = *Oplock;
  if( !*Oplock )
  {
    v11 = FsRtlpAllocateOplock();
    *Oplock = v11;
  }
  v55 = v11;
  ExAcquireFastMutexUnsafe(v11->FastMutex);
  if( (v11->OplockState & 0x10000) != 0 && v9->MajorFunction == 13 )
  {
    FsRtlpCallerIsAtomicRequestor((INT64)v11, v9->FileObject, (INT64)&a3, v12, v50);
    if( v14 )
    {
      if( (v13 & 0x20000) != 0 )
      {
        v15 = (_RH_OP_CONTEXT *)a3;
        FsRtlpOplockDequeueRH((_RH_OP_CONTEXT *)a3);
        Flink = v15->AtomicLinks.Flink;
        Blink = v15->AtomicLinks.Blink;
        if( Flink->Blink != &v15->AtomicLinks || Blink->Flink != &v15->AtomicLinks )
          __fastfail(3u);
        Blink->Flink = Flink;
        Flink->Blink = Blink;
        if( v11->AtomicQueue.Flink == &v11->AtomicQueue )
          v11->OplockState &= 0xFFFCFFFF;
        if( v15->OplockOwnerThread )
          FsRtlpClearOwner(v11, v15);
        ExFreePoolWithTag(v15, 0);
        a3 = 0i64;
        FsRtlpComputeShareableOplockState(v11);
LABEL_14:
        v18 = -1073741598;
LABEL_15:
        v19 = 1;
        goto LABEL_104;
      }
      for( i = (_WAITING_IRP *)v11->WaitingIrps.Flink;
            i != (_WAITING_IRP *)&v11->WaitingIrps;
            i = (_WAITING_IRP *)i->Links.Flink )
      {
        v21 = i;
        if( !i->OplockBreakNotify )
        {
          i = (_WAITING_IRP *)i->Links.Blink;
          FsRtlpRemoveAndCompleteWaitingIrp(v21);
        }
      }
      v22 = (_RH_OP_CONTEXT *)a3;
      FsRtlpOplockDequeueRH((_RH_OP_CONTEXT *)a3);
      v23 = v22->AtomicLinks.Flink;
      v24 = v22->AtomicLinks.Blink;
      if( v23->Blink != &v22->AtomicLinks || v24->Flink != &v22->AtomicLinks )
        __fastfail(3u);
      v24->Flink = v23;
      v23->Blink = v24;
      if( v11->AtomicQueue.Flink == &v11->AtomicQueue )
        v11->OplockState &= 0xFFFCFFFF;
      if( v22->OplockOwnerThread )
        FsRtlpClearOwner(v11, v22);
      ExFreePoolWithTag(v22, 0);
      a3 = 0i64;
      FsRtlpComputeShareableOplockState(v11);
      v9 = IrpSp;
    }
  }
  if( !FsRtlpOplockUpperLowerCompatible((unsigned int)NextOplockState, (unsigned int)LowerOplockLevel) )
  {
    Irp->IoStatus.Status = -1073741598;
    LOBYTE(v19) = v25;
    IofCompleteRequest(Irp, v19);
    goto LABEL_105;
  }
  if( (_DWORD)NextOplockState == 200 )
  {
    v11->IrpExclusiveOplock = Irp;
    v11->FileObject = v9->FileObject;
    v11->OplockState = v11->OplockState & 0x20 | 0xC8;
    goto LABEL_105;
  }
  OplockState = v11->OplockState;
  if( (OplockState & 0x91) == 0 )
  {
    if( (OplockState & 0x7000) != 0 && (OplockState & 0x1F00F00) == 0 && v11->RHBreakQueue.Flink == &v11->RHBreakQueue )
    {
      if( (NextOplockState & 0x10000) != 0 )
        goto LABEL_105;
      if( (NextOplockState & 0x7000) != 0 && (!v9->FileObject->DeletePending || (NextOplockState & 0x2000) == 0) )
      {
        v32 = OplockState & 0x1F0FFDF;
        if( v32 == 4096 )
        {
          if( (((_DWORD)NextOplockState - 20544) & 0xFFFFDFFF) == 0 )
          {
            p_IrpOplocksR = &v11->IrpOplocksR;
            for( j = v11->IrpOplocksR.Flink; j != p_IrpOplocksR; j = j->Flink )
            {
              v58 = j[1].Flink;
              FsRtlpOplockKeysEqual(IrpSp->FileObject, (_FILE_OBJECT *)v58[3].Flink, 0i64);
              if( !v47 )
              {
                v18 = -1073741598;
                LOBYTE(v19) = 1;
                goto LABEL_104;
              }
            }
            v25 = 1;
            if( v61 <= 1 || (FsctrlFlags & 1) != 0 )
            {
              for( k = p_IrpOplocksR->Flink; ; k = *p_Flink )
              {
                v54 = (__int64)k;
                if( k == p_IrpOplocksR )
                  break;
                p_Flink = &k->Blink->Flink;
                FsRtlpRemoveAndCompleteReadOnlyIrp(*p_Flink, 533i64, NextOplockState & 0x7000);
              }
              goto LABEL_54;
            }
          }
        }
        else if( v32 == 12288 )
        {
          if( (_DWORD)NextOplockState == 28736 )
          {
            p_IrpOplocksRH = &v11->IrpOplocksRH;
            for( m = v11->IrpOplocksRH.Flink; m != p_IrpOplocksRH; m = m->Flink )
            {
              FsRtlpOplockKeysEqual(IrpSp->FileObject, (_FILE_OBJECT *)m[1].Blink, 0i64);
              if( !v40 )
                goto LABEL_14;
              if( m[3].Blink )
              {
                v18 = -1073741597;
                goto LABEL_15;
              }
            }
            v25 = 1;
            if( v61 <= 1 || (FsctrlFlags & 1) != 0 )
            {
              for( n = (__int64)p_IrpOplocksRH->Flink; ; n = *v42 )
              {
                v54 = n;
                if( (_LIST_ENTRY *)n == p_IrpOplocksRH )
                  break;
                v42 = *(__int64 **)(n + 8);
                v43 = Feature_Servicing_39887415__private_IsEnabled() != 0;
                v44 = (VOID *)*v42;
                if( v43 )
                {
                  LODWORD(v51) = 0;
                  LODWORD(v50) = 0;
                  FsRtlpRemoveAndCompleteRHIrp(v44, v11, 533i64, 0x7000ui64, (INT64)v50, v51, 0);
                }
                else
                {
                  LODWORD(AccessMode) = 0;
                  LODWORD(v51) = 0;
                  LODWORD(v50) = 28672;
                  FsRtlpRemoveAndBreakRHIrp(v44, v11, 1u, 533i64, (UINT64)v50, v51, AccessMode, 0);
                }
              }
              goto LABEL_54;
            }
          }
        }
        else if( (v32 == 20544 || v32 == 28736 && (_DWORD)NextOplockState == 28736)
               && (((_DWORD)NextOplockState - 20544) & 0xFFFFDFFF) == 0 )
        {
          FsRtlpOplockKeysEqual(v9->FileObject, v11->FileObject, 0i64);
          if( !v35 )
            goto LABEL_14;
          IrpExclusiveOplock = v11->IrpExclusiveOplock;
          v36 = (__int64)IrpExclusiveOplock;
          *(_BYTE *)(v36 + 69) = KeAcquireQueuedSpinLock(7i64, v33, v34);
          _InterlockedExchange64((volatile __int64 *)(v36 + 104), 0i64);
          KeReleaseQueuedSpinLock(LockQueueIoCancelLock, *(_BYTE *)(v36 + 69));
          LODWORD(MasterIrp) = (_DWORD)IrpExclusiveOplock;
          if( IrpExclusiveOplock->Cancel )
          {
            *(_QWORD *)(v36 + 56) = 0i64;
            *(_DWORD *)(v36 + 48) = -1073741536;
          }
          else
          {
            MasterIrp = (__int64)IrpExclusiveOplock->AssociatedIrp.MasterIrp;
            v57 = MasterIrp;
            *(_OWORD *)MasterIrp = 0i64;
            *(_QWORD *)(MasterIrp + 16) = 0i64;
            *(_DWORD *)MasterIrp = 1572865;
            *(_DWORD *)(MasterIrp + 4) = (v11->OplockState >> 12) & 7;
            *(_DWORD *)(MasterIrp + 8) = ((unsigned int)NextOplockState >> 12) & 7;
            *(_QWORD *)(v36 + 56) = 24i64;
            *(_DWORD *)(v36 + 48) = 533;
          }
          LOBYTE(MasterIrp) = 1;
          IofCompleteRequest((PIRP)v36, MasterIrp);
          v11->IrpExclusiveOplock = 0i64;
          ObfDereferenceObjectWithTag(v11->FileObject, 0x746C6644ui64);
          v11->FileObject = 0i64;
          goto LABEL_54;
        }
      }
LABEL_39:
      v18 = -1073741598;
      goto LABEL_103;
    }
    if( (NextOplockState & 0x10000) != 0 )
      goto LABEL_105;
LABEL_102:
    v18 = -1073741598;
    if( !Irp )
      goto LABEL_105;
LABEL_103:
    LOBYTE(v19) = v25;
LABEL_104:
    Irp->IoStatus.Status = v18;
    IofCompleteRequest(Irp, v19);
    goto LABEL_105;
  }
  if( (OplockState & 0x10) != 0 )
  {
    if( (NextOplockState & 0x7000) != 0 )
      goto LABEL_37;
    v7 = v61;
  }
  if( (OplockState & 0x80u) != 0 )
  {
    FsRtlpOplockKeysEqual(v9->FileObject, v11->FileObject, 0i64);
    if( !v27 )
    {
      if( (NextOplockState & 0x10000) != 0 )
        goto LABEL_105;
      goto LABEL_14;
    }
  }
  v28 = v11->OplockState & 0x1F0FFDF;
  if( v28 == 16 || v28 == 4096 || v28 == 4112 )
    FsRtlpRemoveAndCompleteReadOnlyIrp(v11->IrpOplocksR.Flink, 0i64, 0i64);
  v25 = 1;
  if( v7 > 1 && (v11->OplockState & 1) != 0 && (FsctrlFlags & 1) == 0 )
    goto LABEL_102;
  if( v9->FileObject->DeletePending && (NextOplockState & 0x2000) != 0 )
  {
LABEL_37:
    if( (NextOplockState & 0x10000) != 0 )
      goto LABEL_105;
    goto LABEL_39;
  }
LABEL_54:
  v11->IrpExclusiveOplock = Irp;
  v11->FileObject = IrpSp->FileObject;
  FsRtlpClearOwner(v11, 0i64);
  v11->ExclusiveOplockOwner = KeGetCurrentThread()->ApcState.Process;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v11->ExclusiveOplockOwnerThread = CurrentThread;
  ObfReferenceObjectWithTag(CurrentThread, 0x746C6644ui64);
  v11->WaiterPriority = 0;
  v11->OplockState = NextOplockState | v11->OplockState & 0x20;
  ObfReferenceObjectWithTag(IrpSp->FileObject, 0x746C6644ui64);
  CurrentStackLocation = Irp->Tail.CurrentStackLocation;
  CurrentStackLocation->Control |= 1u;
  Irp->IoStatus.Information = (unsigned __int64)v11;
  Irp->CancelIrql = KeAcquireQueuedSpinLock(7i64, v30, v31);
  if( Irp->Cancel )
  {
    FsRtlpCancelExclusiveIrp(Irp, 1u, 1u);
  }
  else
  {
    _InterlockedExchange64((volatile __int64 *)&Irp->CancelRoutine, (__int64)FsRtlpExclusiveIrpCancelRoutine);
    KeReleaseQueuedSpinLock(LockQueueIoCancelLock, Irp->CancelIrql);
  }
LABEL_105:
  ExReleaseFastMutexUnsafe(v11->FastMutex);
}

Referenced by:

FsRtlpOplockFsctrlInternal