FsRtlpWaitOnIrp

__int64 __fastcall FsRtlpWaitOnIrp(
        __int64 a1,
        __int64 a2,
        void *a3,
        void (__fastcall *a4)(void *, _IRP *),
        void (__fastcall *a5)(void *, __int64),
        char *Object,
        unsigned __int8 a7,
        __int64 a8,
        __int64 a9,
        void (__fastcall *a10)(__int128 *),
        _WAITING_IRP *a11){
  char v15; 
  _WAITING_IRP *v16; 
  _WAITING_IRP *PoolWithTag; 
  INT64 v18; 
  INT64 v19; 
  __int64 v20; 
  bool v21; 
  _WAITING_IRP **v22; 
  unsigned int v23; 
  bool v24; 
  NTSTATUS v25; 
  void *v26; 
  void *v27; 
  void *v28; 
  _WAITING_IRP *i; 
  _BYTE v31[7]; 
  _WAITING_IRP *v32; 
  __int128 v33; 
  __int128 v34; 

  v15 = 1;
  v16 = (_WAITING_IRP *)v31;
  if( a11 )
    v16 = a11;
  v32 = v16;
  LOBYTE(v16->Links.Flink) = 0;
  PoolWithTag = (_WAITING_IRP *)ExAllocatePoolWithTag(0x11ui64, 0x40ui64, 1869763398i64);
  a11 = PoolWithTag;
  memset(PoolWithTag, 0i64, sizeof(_WAITING_IRP));
  if( a2 )
  {
    v20 = *(_QWORD *)(a2 + 184);
    PoolWithTag->Irp = (_IRP *)a2;
    PoolWithTag->Information = *(_DWORD *)(a2 + 56);
    v21 = *(_BYTE *)v20 == 13 && *(_DWORD *)(v20 + 24) == 589844;
    PoolWithTag->OplockBreakNotify = v21;
    PoolWithTag->FileObject = *(_FILE_OBJECT **)(v20 + 48);
  }
  PoolWithTag->BreakAllRH = a7;
  if( a4 )
  {
    PoolWithTag->CompletionRoutine = a4;
    PoolWithTag->Context = a3;
  }
  else
  {
    PoolWithTag->CompletionRoutine = (void(__fastcall *)(void *, _IRP *))FsRtlpOplockWaitCompleteRoutine;
    PoolWithTag->Context = Object;
    *(_WORD *)Object = 0;
    Object[2] = 6;
    *((_DWORD *)Object + 1) = 0;
    *((_QWORD *)Object + 2) = Object + 8;
    *((_QWORD *)Object + 1) = Object + 8;
  }
  if( a5 )
    a5(a3, a2);
  v22 = *(_WAITING_IRP ***)(a1 + 96);
  if( *v22 != (_WAITING_IRP *)(a1 + 88) )
    __fastfail(3u);
  PoolWithTag->Links.Flink = (_LIST_ENTRY *)(a1 + 88);
  PoolWithTag->Links.Blink = (_LIST_ENTRY *)v22;
  *v22 = PoolWithTag;
  *(_QWORD *)(a1 + 96) = PoolWithTag;
  if( a2 )
  {
    *(_DWORD *)(a2 + 48) = 0;
    *(_BYTE *)(a2 + 69) = KeAcquireQueuedSpinLock(7i64, v18, v19);
    *(_QWORD *)(a2 + 56) = a1;
    if( *(_BYTE *)(a2 + 68) )
    {
      if( a4 )
      {
        *(_BYTE *)(*(_QWORD *)(a2 + 184) + 3i64) |= 1u;
        v23 = 259;
      }
      else
      {
        v23 = -1073741536;
      }
      *(_DWORD *)&v31[3] = v23;
      FsRtlpCancelWaitingIrp((_IRP *)a2, 1u);
      goto LABEL_51;
    }
    _InterlockedExchange64((volatile __int64 *)(a2 + 104), (__int64)FsRtlpWaitingIrpCancelRoutine);
    KeReleaseQueuedSpinLock(LockQueueIoCancelLock, *(_BYTE *)(a2 + 69));
    v15 = 1;
    PoolWithTag = a11;
  }
  if( a4 )
  {
    if( a2 )
      *(_BYTE *)(*(_QWORD *)(a2 + 184) + 3i64) |= 1u;
    v23 = 259;
    *(_DWORD *)&v31[3] = 259;
  }
  else
  {
    v24 = a8 && a10;
    LOBYTE(a11) = 0;
    v33 = 0i64;
    v34 = 0i64;
    ExReleaseFastMutexUnsafe(*(PFAST_MUTEX *)(a1 + 152));
    v15 = 0;
    while( 1 )
    {
      v25 = FsRtlCancellableWaitForSingleObject(
              Object,
              (_LARGE_INTEGER *)((unsigned __int64)&a8 & -(__int64)v24),
              (_IRP *)a2);
      v23 = v25;
      *(_DWORD *)&v31[3] = v25;
      if( !v24 || v25 != 258 )
        break;
      v24 = 0;
      *(_QWORD *)&v33 = 0i64;
      *((_QWORD *)&v33 + 1) = a9;
      *(_QWORD *)&v34 = a2;
      *((_QWORD *)&v34 + 1) = 258i64;
      a10(&v33);
      LOBYTE(a11) = 1;
    }
    if( (_BYTE)a11 )
    {
      LODWORD(v33) = 1;
      DWORD2(v34) = v25;
      a10(&v33);
    }
    if( v23 == -1073741749 || v23 == -1073741536 )
    {
      if( a2 )
      {
        IoCancelIrp((_KDPC *)a2, v26, v27, v28);
      }
      else
      {
        ExAcquireFastMutex(*(PFAST_MUTEX *)(a1 + 152));
        for( i = *(_WAITING_IRP **)(a1 + 88); i != (_WAITING_IRP *)(a1 + 88); i = (_WAITING_IRP *)i->Links.Flink )
        {
          if( PoolWithTag == i )
          {
            FsRtlpRemoveAndCompleteWaitingIrp(i);
            break;
          }
        }
        KeReleaseGuardedMutex(*(PKGUARDED_MUTEX *)(a1 + 152));
      }
      KeWaitForSingleObject((UINT64)Object, 0, 0, 0, 0i64);
      LOBYTE(v32->Links.Flink) = 0;
    }
    else
    {
      if( a2 )
      {
        v23 = *(_DWORD *)(a2 + 48);
        *(_DWORD *)&v31[3] = v23;
      }
      LOBYTE(v32->Links.Flink) = 1;
    }
  }
LABEL_51:
  if( v15 )
    ExReleaseFastMutexUnsafe(*(PFAST_MUTEX *)(a1 + 152));
  return v23;
}

Referenced by:

FsRtlpOplockBreakByCacheFlags
FsRtlpOplockBreakNotify
FsRtlpOplockBreakToII
FsRtlpOplockBreakToNone