FsRtlpRequestShareableOplock

NTSTATUS __stdcall FsRtlpRequestShareableOplock(
        _NONOPAQUE_OPLOCK **Oplock,
        _IO_STACK_LOCATION *IrpSp,
        _IRP *Irp,
        UINT64 DesiredOplock,
        _RH_OP_CONTEXT **NewRHOpContext,
        UINT8 RefFileObject,
        UINT8 GrantingInAck,
        UINT64 LowerOplockLevel){
  unsigned int v8; 
  _IO_STACK_LOCATION *v10; 
  NTSTATUS v12; 
  char v13; 
  _NONOPAQUE_OPLOCK *v14; 
  UINT8 v15; 
  int v16; 
  char v17; 
  _RH_OP_CONTEXT *v18; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *Blink; 
  _CCHAR v21; 
  _WAITING_IRP *i; 
  _WAITING_IRP *v23; 
  _RH_OP_CONTEXT *v24; 
  _LIST_ENTRY *v25; 
  _LIST_ENTRY *v26; 
  __int64 v27; 
  unsigned int v28; 
  int v29; 
  int v30; 
  _LIST_ENTRY *m; 
  char v32; 
  _LIST_ENTRY *n; 
  char v34; 
  VOID **p_Flink; 
  NTSTATUS IsEnabled; 
  VOID *v37; 
  _LIST_ENTRY *v38; 
  char v39; 
  int v40; 
  _CCHAR v41; 
  _LIST_ENTRY *p_AtomicLinks; 
  _LIST_ENTRY *p_AtomicQueue; 
  _LIST_ENTRY *v44; 
  INT64 v45; 
  INT64 v46; 
  unsigned int OplockState; 
  int v48; 
  unsigned int v49; 
  int v50; 
  _LIST_ENTRY *v51; 
  char v52; 
  _LIST_ENTRY *j; 
  char v54; 
  int v55; 
  _LIST_ENTRY *k; 
  _LIST_ENTRY *v57; 
  char v58; 
  _LIST_ENTRY *p_ListEntry; 
  _LIST_ENTRY *p_IrpOplocksR; 
  _LIST_ENTRY *v61; 
  INT64 v62; 
  INT64 v63; 
  _RH_OP_CONTEXT **v65; 
  INT64 v66; 
  UINT64 AccessMode; 
  INT64 a3; 
  PFAST_MUTEX FastMutex; 
  _ETHREAD *CurrentThread; 
  _IO_STACK_LOCATION *v71; 
  _IO_STACK_LOCATION *CurrentStackLocation; 
  char v73; 

  v8 = DesiredOplock;
  v10 = IrpSp;
  v12 = 0;
  a3 = 0i64;
  FastMutex = 0i64;
  v73 = 0;
  v13 = 0;
  v14 = *Oplock;
  if( !*Oplock )
  {
    v14 = FsRtlpAllocateOplock();
    *Oplock = v14;
  }
  v15 = GrantingInAck;
  if( !GrantingInAck && v8 != 0x10000 )
  {
    FastMutex = v14->FastMutex;
    ExAcquireFastMutexUnsafe(FastMutex);
    v73 = 1;
  }
  if( (v14->OplockState & 0x10000) != 0 && v10->MajorFunction == 13 )
  {
    FsRtlpCallerIsAtomicRequestor((INT64)v14, v10->FileObject, (INT64)&a3, DesiredOplock, v65);
    if( v17 )
    {
      if( (v16 & 0x20000) != 0 )
      {
        v18 = (_RH_OP_CONTEXT *)a3;
        FsRtlpOplockDequeueRH((_RH_OP_CONTEXT *)a3);
        Flink = v18->AtomicLinks.Flink;
        Blink = v18->AtomicLinks.Blink;
        if( Flink->Blink != &v18->AtomicLinks || Blink->Flink != &v18->AtomicLinks )
          __fastfail(3u);
        Blink->Flink = Flink;
        Flink->Blink = Blink;
        if( v14->AtomicQueue.Flink == &v14->AtomicQueue )
          v14->OplockState &= 0xFFFCFFFF;
        if( v18->OplockOwnerThread )
          FsRtlpClearOwner(v14, v18);
        ExFreePoolWithTag(v18, 0);
        a3 = 0i64;
        FsRtlpComputeShareableOplockState(v14);
LABEL_138:
        Irp->IoStatus.Status = -1073741598;
        LOBYTE(v21) = 1;
        IofCompleteRequest(Irp, v21);
LABEL_139:
        v12 = -1073741598;
        goto LABEL_140;
      }
      for( i = (_WAITING_IRP *)v14->WaitingIrps.Flink;
            i != (_WAITING_IRP *)&v14->WaitingIrps;
            i = (_WAITING_IRP *)i->Links.Flink )
      {
        v23 = i;
        if( !i->OplockBreakNotify || v8 != 12288 )
        {
          i = (_WAITING_IRP *)i->Links.Blink;
          FsRtlpRemoveAndCompleteWaitingIrp(v23);
        }
      }
      v24 = (_RH_OP_CONTEXT *)a3;
      FsRtlpOplockDequeueRH((_RH_OP_CONTEXT *)a3);
      v25 = v24->AtomicLinks.Flink;
      v26 = v24->AtomicLinks.Blink;
      if( v25->Blink != &v24->AtomicLinks || v26->Flink != &v24->AtomicLinks )
        __fastfail(3u);
      v26->Flink = v25;
      v25->Blink = v26;
      if( v14->AtomicQueue.Flink == &v14->AtomicQueue )
        v14->OplockState &= 0xFFFCFFFF;
      if( v24->OplockOwnerThread )
        FsRtlpClearOwner(v14, v24);
      ExFreePoolWithTag(v24, 0);
      a3 = 0i64;
      FsRtlpComputeShareableOplockState(v14);
      v10 = IrpSp;
      v15 = GrantingInAck;
    }
  }
  if( !FsRtlpOplockUpperLowerCompatible(v8, (unsigned int)LowerOplockLevel) )
  {
    Irp->IoStatus.Status = -1073741598;
    LOBYTE(v21) = 1;
    IofCompleteRequest(Irp, v21);
    goto LABEL_140;
  }
  if( !v15 && (v14->OplockState & 0x40) != 0 )
  {
LABEL_36:
    if( v8 == 0x10000 )
    {
      v12 = -1073739511;
      goto LABEL_140;
    }
    goto LABEL_138;
  }
  if( v8 == 16 )
  {
    OplockState = v14->OplockState;
    if( (OplockState & 1) == 0 )
    {
      v48 = OplockState & 0x1F0FFDF;
      if( v48 != 16 && v48 != 4096 && v48 != 4112 )
        goto LABEL_138;
    }
    goto LABEL_99;
  }
  if( v8 == 4096 )
  {
LABEL_99:
    if( !v15 )
    {
      v49 = v14->OplockState;
      if( (v49 & 1) == 0 )
      {
        v50 = v49 & 0x1F0FFDF;
        if( (v49 & 0x1F0FFDF) != 16
          && v50 != 4096
          && v50 != 4112
          && v50 != 12288
          && v50 != 45056
          && v50 != 1060864
          && v50 != 8400896
          && (v49 & 0x10000) == 0 )
        {
          goto LABEL_138;
        }
      }
      v51 = v14->IrpOplocksRH.Flink;
      if( v51 != &v14->IrpOplocksRH )
        goto LABEL_112;
      if( v14->RHBreakQueue.Flink != &v14->RHBreakQueue )
      {
        while( v51 != &v14->IrpOplocksRH )
        {
LABEL_112:
          FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)v51[1].Blink, 0i64);
          if( v52 )
            goto LABEL_138;
          v51 = v51->Flink;
        }
        for( j = v14->RHBreakQueue.Flink; j != &v14->RHBreakQueue; j = j->Flink )
        {
          FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)j[1].Blink, 0i64);
          if( v54 )
            goto LABEL_138;
        }
      }
      v55 = v14->OplockState & 0x1F0FFDF;
      if( v55 == 16 || v55 == 4096 || v55 == 4112 || v55 == 45056 )
      {
        for( k = v14->IrpOplocksR.Flink; k != &v14->IrpOplocksR; k = k->Flink )
        {
          v57 = k[1].Flink;
          if( LODWORD(v57[1].Blink) == 590400 || v57[3].Flink != (_LIST_ENTRY *)v10->FileObject )
          {
            FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)v57[3].Flink, 0i64);
            if( v58 )
            {
              FsRtlpRemoveAndCompleteReadOnlyIrp(k->Blink->Flink, 533i64, v8 & 0x7000);
              break;
            }
          }
        }
      }
    }
    CurrentStackLocation = Irp->Tail.CurrentStackLocation;
    CurrentStackLocation->Control |= 1u;
    Irp->IoStatus.Status = 0;
    p_ListEntry = &Irp->Tail.ListEntry;
    p_IrpOplocksR = &v14->IrpOplocksR;
    v61 = v14->IrpOplocksR.Flink;
    if( v61->Blink != &v14->IrpOplocksR )
      __fastfail(3u);
    p_ListEntry->Flink = v61;
    Irp->Tail.ListEntry.Blink = p_IrpOplocksR;
    v61->Blink = p_ListEntry;
    p_IrpOplocksR->Flink = p_ListEntry;
    Irp->IoStatus.Information = (unsigned __int64)v14;
    FsRtlpComputeShareableOplockState(v14);
    if( RefFileObject )
      ObfReferenceObjectWithTag(v10->FileObject, 0x746C6644ui64);
    Irp->CancelIrql = KeAcquireQueuedSpinLock(7i64, v62, v63);
    if( Irp->Cancel )
    {
      FsRtlpCancelReadOnlyOplockIrp(Irp, 1u);
    }
    else
    {
      _InterlockedExchange64((volatile __int64 *)&Irp->CancelRoutine, (__int64)FsRtlpReadOnlyOplockIrpCancelRoutine);
      KeReleaseQueuedSpinLock(LockQueueIoCancelLock, Irp->CancelIrql);
    }
    v13 = 1;
    v12 = 259;
LABEL_137:
    if( v13 )
      goto LABEL_140;
    goto LABEL_138;
  }
  if( v8 != 12288 && v8 != 0x10000 )
    goto LABEL_137;
  if( !v15 )
  {
    v28 = v14->OplockState;
    if( (v28 & 1) == 0 )
    {
      v29 = v28 & 0x1F0FFDF;
      if( (v28 & 0x1F0FFDF) != 4096
        && v29 != 12288
        && v29 != 45056
        && v29 != 1060864
        && v29 != 8400896
        && (v28 & 0x10000) == 0 )
      {
        goto LABEL_36;
      }
    }
  }
  if( v10->FileObject->DeletePending )
    goto LABEL_36;
  if( !v15 )
  {
    v30 = v14->OplockState & 0x1F0FFDF;
    if( v30 == 4096 || v30 == 45056 )
    {
      for( m = v14->IrpOplocksR.Flink; m != &v14->IrpOplocksR; m = m->Flink )
      {
        FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)m[1].Flink[3].Flink, 0i64);
        if( v32 )
        {
          if( v8 == 0x10000 )
          {
            v12 = -1073741597;
            goto LABEL_140;
          }
          FsRtlpRemoveAndCompleteReadOnlyIrp(m->Blink->Flink, 533i64, 0x3000ui64);
          break;
        }
      }
    }
    if( (((v14->OplockState & 0x1F0FFDF) - 12288) & 0xFFFF7FFF) == 0 )
    {
      for( n = v14->IrpOplocksRH.Flink; n != &v14->IrpOplocksRH; n = n->Flink )
      {
        FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)n[1].Blink, 0i64);
        if( v34 && !n[3].Blink )
        {
          if( v8 == 0x10000 )
          {
            v12 = -1073741597;
            goto LABEL_140;
          }
          p_Flink = (VOID **)&n->Blink->Flink;
          IsEnabled = Feature_Servicing_39887415__private_IsEnabled();
          v37 = *p_Flink;
          if( IsEnabled )
          {
            LODWORD(v66) = 0;
            LODWORD(v65) = 0;
            FsRtlpRemoveAndCompleteRHIrp(v37, v14, 533i64, 0x3000ui64, (INT64)v65, v66, 0);
          }
          else
          {
            LODWORD(AccessMode) = 0;
            LODWORD(v66) = 0;
            LODWORD(v65) = 12288;
            FsRtlpRemoveAndBreakRHIrp(v37, v14, 1u, 533i64, (UINT64)v65, v66, AccessMode, 0);
          }
          break;
        }
      }
    }
    v38 = v14->RHBreakQueue.Flink;
    if( v38 != &v14->RHBreakQueue )
    {
      while( v38 != &v14->RHBreakQueue )
      {
        FsRtlpOplockKeysEqual(v10->FileObject, (_FILE_OBJECT *)v38[1].Blink, 0i64);
        if( v39 )
        {
          if( v8 == 0x10000 )
            goto LABEL_139;
          goto LABEL_138;
        }
        v38 = v38->Flink;
      }
    }
  }
  (*NewRHOpContext)->OplockRequestProcess = KeGetCurrentThread()->ApcState.Process;
  (*NewRHOpContext)->OplockRequestFileObject = v10->FileObject;
  v40 = FsRtlpOplockEnqueueRH(&v14->IrpOplocksRH, *NewRHOpContext, v27);
  v12 = v40;
  if( v40 >= 0 )
  {
    if( v8 == 0x10000 )
    {
      p_AtomicLinks = &(*NewRHOpContext)->AtomicLinks;
      p_AtomicQueue = &v14->AtomicQueue;
      v44 = v14->AtomicQueue.Flink;
      if( v44->Blink != &v14->AtomicQueue )
        __fastfail(3u);
      p_AtomicLinks->Flink = v44;
      p_AtomicLinks->Blink = p_AtomicQueue;
      v44->Blink = p_AtomicLinks;
      p_AtomicQueue->Flink = p_AtomicLinks;
      v12 = 0;
    }
    else
    {
      CurrentThread = (_ETHREAD *)KeGetCurrentThread();
      (*NewRHOpContext)->OplockOwnerThread = CurrentThread;
      ObfReferenceObjectWithTag((*NewRHOpContext)->OplockOwnerThread, 0x746C6644ui64);
      (*NewRHOpContext)->OplockRequestIrp = Irp;
      v71 = Irp->Tail.CurrentStackLocation;
      v71->Control |= 1u;
      v12 = 259;
      Irp->IoStatus.Status = 0;
      Irp->IoStatus.Information = (unsigned __int64)v14;
      if( RefFileObject )
        ObfReferenceObjectWithTag((*NewRHOpContext)->OplockRequestFileObject, 0x746C6644ui64);
      Irp->CancelIrql = KeAcquireQueuedSpinLock(7i64, v45, v46);
      if( Irp->Cancel )
      {
        if( RefFileObject && GrantingInAck )
          FsRtlpCancelOplockRHIrp(Irp, 1u, 0);
        else
          FsRtlpCancelOplockRHIrp(Irp, 1u, 1u);
      }
      else
      {
        _InterlockedExchange64((volatile __int64 *)&Irp->CancelRoutine, (__int64)FsRtlpOplockRHIrpCancelRoutine);
        KeReleaseQueuedSpinLock(LockQueueIoCancelLock, Irp->CancelIrql);
        v12 = 259;
      }
    }
    *NewRHOpContext = 0i64;
    FsRtlpComputeShareableOplockState(v14);
    if( v8 == 0x10000 )
      v14->OplockState |= 0x10000u;
  }
  else if( v8 != 0x10000 )
  {
    Irp->IoStatus.Status = v40;
    LOBYTE(v41) = 1;
    IofCompleteRequest(Irp, v41);
  }
LABEL_140:
  if( v73 && v8 != 0x10000 )
    ExReleaseFastMutexUnsafe(FastMutex);
  return v12;
}

Referenced by:

FsRtlpAcknowledgeOplockBreakByCacheFlags
FsRtlpGrantAnyOplockFromExclusive
FsRtlpOplockFsctrlInternal