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