ReactOS  0.4.14-dev-317-g96040ec
oplock.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for oplock.c:

Go to the source code of this file.

Classes

struct  _INTERNAL_OPLOCK
 
struct  _WAIT_CONTEXT
 

Macros

#define NDEBUG
 
#define NO_OPLOCK   0x1
 
#define LEVEL_1_OPLOCK   0x2
 
#define BATCH_OPLOCK   0x4
 
#define FILTER_OPLOCK   0x8
 
#define LEVEL_2_OPLOCK   0x10
 
#define EXCLUSIVE_LOCK   0x40
 
#define PENDING_LOCK   0x80
 
#define BROKEN_TO_LEVEL_2   0x100
 
#define BROKEN_TO_NONE   0x200
 
#define BROKEN_TO_NONE_FROM_LEVEL_2   0x400
 
#define BROKEN_TO_CLOSE_PENDING   0x800
 
#define BROKEN_ANY   (BROKEN_TO_LEVEL_2 | BROKEN_TO_NONE | BROKEN_TO_NONE_FROM_LEVEL_2 | BROKEN_TO_CLOSE_PENDING)
 
#define TAG_OPLOCK   'orSF'
 
#define BreakToIIIfRequired
 
#define BreakToNoneIfRequired
 

Typedefs

typedef struct _INTERNAL_OPLOCK INTERNAL_OPLOCK
 
typedef struct _INTERNAL_OPLOCKPINTERNAL_OPLOCK
 
typedef struct _WAIT_CONTEXT WAIT_CONTEXT
 
typedef struct _WAIT_CONTEXTPWAIT_CONTEXT
 

Functions

VOID NTAPI FsRtlNotifyCompletion (IN PVOID Context, IN PIRP Irp)
 
VOID NTAPI FsRtlCompletionRoutinePriv (IN PVOID Context, IN PIRP Irp)
 
VOID FsRtlRemoveAndCompleteWaitIrp (IN PWAIT_CONTEXT WaitCtx)
 
VOID NTAPI FsRtlCancelWaitIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
VOID FsRtlWaitOnIrp (IN PINTERNAL_OPLOCK Oplock, IN PIRP Irp, IN PVOID CompletionContext, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine, IN PKEVENT WaitEvent)
 
NTSTATUS FsRtlOplockBreakNotify (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
 
VOID FsRtlRemoveAndCompleteIrp (IN PIRP Irp)
 
VOID NTAPI FsRtlCancelOplockIIIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS FsRtlAcknowledgeOplockBreak (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN BOOLEAN SwitchToLevel2)
 
NTSTATUS FsRtlOpBatchBreakClosePending (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
 
PINTERNAL_OPLOCK FsRtlAllocateOplock (VOID)
 
VOID NTAPI FsRtlCancelExclusiveIrp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS FsRtlRequestExclusiveOplock (IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN ULONG Flags)
 
NTSTATUS FsRtlRequestOplockII (IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
 
VOID FsRtlOplockCleanup (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack)
 
NTSTATUS NTAPI FsRtlOplockBreakToNone (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
 
NTSTATUS NTAPI FsRtlOplockBreakToII (IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
 
NTSTATUS NTAPI FsRtlCheckOplock (IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
 
BOOLEAN NTAPI FsRtlCurrentBatchOplock (IN POPLOCK Oplock)
 
VOID NTAPI FsRtlInitializeOplock (IN OUT POPLOCK Oplock)
 
NTSTATUS NTAPI FsRtlOplockFsctrl (IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
 
BOOLEAN NTAPI FsRtlOplockIsFastIoPossible (IN POPLOCK Oplock)
 
VOID NTAPI FsRtlUninitializeOplock (IN POPLOCK Oplock)
 

Macro Definition Documentation

◆ BATCH_OPLOCK

#define BATCH_OPLOCK   0x4

Definition at line 17 of file oplock.c.

◆ BreakToIIIfRequired

#define BreakToIIIfRequired
Value:
if (IntOplock->Flags != LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
_In_ PIRP Irp
Definition: csq.h:116
NTSTATUS NTAPI FsRtlOplockBreakToII(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1037
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673

◆ BreakToNoneIfRequired

#define BreakToNoneIfRequired
Value:
if (IntOplock->Flags == LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
_In_ PIRP Irp
Definition: csq.h:116
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
NTSTATUS NTAPI FsRtlOplockBreakToNone(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:903
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673

◆ BROKEN_ANY

◆ BROKEN_TO_CLOSE_PENDING

#define BROKEN_TO_CLOSE_PENDING   0x800

Definition at line 27 of file oplock.c.

◆ BROKEN_TO_LEVEL_2

#define BROKEN_TO_LEVEL_2   0x100

Definition at line 24 of file oplock.c.

◆ BROKEN_TO_NONE

#define BROKEN_TO_NONE   0x200

Definition at line 25 of file oplock.c.

◆ BROKEN_TO_NONE_FROM_LEVEL_2

#define BROKEN_TO_NONE_FROM_LEVEL_2   0x400

Definition at line 26 of file oplock.c.

◆ EXCLUSIVE_LOCK

#define EXCLUSIVE_LOCK   0x40

Definition at line 21 of file oplock.c.

◆ FILTER_OPLOCK

#define FILTER_OPLOCK   0x8

Definition at line 18 of file oplock.c.

◆ LEVEL_1_OPLOCK

#define LEVEL_1_OPLOCK   0x2

Definition at line 16 of file oplock.c.

◆ LEVEL_2_OPLOCK

#define LEVEL_2_OPLOCK   0x10

Definition at line 19 of file oplock.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file oplock.c.

◆ NO_OPLOCK

#define NO_OPLOCK   0x1

Definition at line 15 of file oplock.c.

◆ PENDING_LOCK

#define PENDING_LOCK   0x80

Definition at line 22 of file oplock.c.

◆ TAG_OPLOCK

#define TAG_OPLOCK   'orSF'

Definition at line 30 of file oplock.c.

Typedef Documentation

◆ INTERNAL_OPLOCK

◆ PINTERNAL_OPLOCK

◆ PWAIT_CONTEXT

◆ WAIT_CONTEXT

Function Documentation

◆ FsRtlAcknowledgeOplockBreak()

NTSTATUS FsRtlAcknowledgeOplockBreak ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp,
IN BOOLEAN  SwitchToLevel2 
)

Definition at line 358 of file oplock.c.

362 {
363  PLIST_ENTRY NextEntry;
364  PWAIT_CONTEXT WaitCtx;
365  BOOLEAN Deref;
366  BOOLEAN Locked;
367 
368  DPRINT("FsRtlAcknowledgeOplockBreak(%p, %p, %p, %u)\n", Oplock, Stack, Irp, Unknown);
369 
370  /* No oplock, nothing to acknowledge */
371  if (Oplock == NULL)
372  {
373  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
376  }
377 
378  /* Acquire oplock internal lock */
379  ExAcquireFastMutexUnsafe(Oplock->IntLock);
380  Locked = TRUE;
381  /* Does it match the file? */
382  if (Oplock->FileObject != Stack->FileObject)
383  {
384  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
386  ExReleaseFastMutexUnsafe(Oplock->IntLock);
388  }
389 
390  /* Assume we'll have to deref our extra ref (level I) */
391  Deref = TRUE;
392 
393  /* If we got broken to level 2 and asked for a shared lock
394  * switch the oplock to shared
395  */
396  if (SwitchToLevel2 && BooleanFlagOn(Oplock->Flags, BROKEN_TO_LEVEL_2))
397  {
398  /* The IRP cannot be synchronous, we'll move it to the LEVEL_2 IRPs */
400 
401  /* Mark the IRP pending, and queue it for the shared IRPs */
403  Irp->IoStatus.Status = STATUS_SUCCESS;
404  InsertTailList(&Oplock->SharedListHead, &Irp->Tail.Overlay.ListEntry);
405 
406  /* Don't deref, we're not done yet */
407  Deref = FALSE;
408  /* And mark we've got a shared lock */
409  Oplock->Flags = LEVEL_2_OPLOCK;
410  /* To find the lock back on cancel */
411  Irp->IoStatus.Information = (ULONG_PTR)Oplock;
412 
413  /* Acquire the spinlock to set the cancel routine */
414  IoAcquireCancelSpinLock(&Irp->CancelIrql);
415  /* If IRP got canceled, call it immediately */
416  if (Irp->Cancel)
417  {
418  ExReleaseFastMutexUnsafe(Oplock->IntLock);
419  Locked = FALSE;
421  }
422  /* Otherwise, just set our cancel routine */
423  else
424  {
426  IoReleaseCancelSpinLock(Irp->CancelIrql);
427  }
428  }
429  /* If oplock got broken, remove it */
430  else if (BooleanFlagOn(Oplock->Flags, (BROKEN_TO_NONE | BROKEN_TO_LEVEL_2)))
431  {
432  Irp->IoStatus.Status = STATUS_SUCCESS;
434  Oplock->Flags = NO_OPLOCK;
435  }
436  /* Same, but precise we got broken from none to shared */
437  else if (BooleanFlagOn(Oplock->Flags, BROKEN_TO_NONE_FROM_LEVEL_2))
438  {
439  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
440  Irp->IoStatus.Status = STATUS_SUCCESS;
442  Oplock->Flags = NO_OPLOCK;
443  }
444 
445  /* Now, complete any IRP waiting */
446  for (NextEntry = Oplock->WaitListHead.Flink;
447  NextEntry != &Oplock->WaitListHead;
448  NextEntry = NextEntry->Flink)
449  {
450  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
452  }
453 
454  /* If we dropped oplock, remove our extra ref */
455  if (Deref)
456  {
457  ObDereferenceObject(Oplock->FileObject);
458  }
459  /* And unset FO: no oplock left or shared */
460  Oplock->FileObject = NULL;
461 
462  /* Don't leak the mutex! */
463  if (Locked)
464  {
465  ExReleaseFastMutexUnsafe(Oplock->IntLock);
466  }
467 
468  return STATUS_SUCCESS;
469 }
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define STATUS_INVALID_OPLOCK_PROTOCOL
Definition: ntstatus.h:449
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
#define InsertTailList(ListHead, Entry)
#define BROKEN_TO_NONE
Definition: oplock.c:25
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID FASTCALL IofCompleteRequest(IN PIRP Irp, IN CCHAR PriorityBoost)
Definition: irp.c:1308
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define ULONG_PTR
Definition: config.h:101
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
VOID NTAPI FsRtlCancelOplockIIIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:313

Referenced by FsRtlOplockFsctrl().

◆ FsRtlAllocateOplock()

PINTERNAL_OPLOCK FsRtlAllocateOplock ( VOID  )

Definition at line 544 of file oplock.c.

545 {
546  PINTERNAL_OPLOCK Oplock = NULL;
547 
548  PAGED_CODE();
549 
550  DPRINT("FsRtlAllocateOplock()\n");
551 
552  _SEH2_TRY
553  {
554  /* Allocate and initialize the oplock */
556  RtlZeroMemory(Oplock, sizeof(INTERNAL_OPLOCK));
557  /* We allocate the fast mutex separately to have it non paged (while the rest of the oplock can be paged) */
560  /* Initialize the IRP list for level 2 oplock */
562  /* And for the wait IRPs */
564  Oplock->Flags = NO_OPLOCK;
565  }
567  {
568  /* In case of abnormal termination, it means either OPLOCK or FAST_MUTEX allocation failed */
570  {
571  /* That FAST_MUTEX, free OPLOCK */
572  if (Oplock != NULL)
573  {
574  ExFreePoolWithTag(Oplock, TAG_OPLOCK);
575  Oplock = NULL;
576  }
577  }
578  }
579  _SEH2_END;
580 
581  return Oplock;
582 }
PFAST_MUTEX IntLock
Definition: oplock.c:43
LIST_ENTRY SharedListHead
Definition: oplock.c:39
#define POOL_COLD_ALLOCATION
LIST_ENTRY WaitListHead
Definition: oplock.c:41
#define TAG_OPLOCK
Definition: oplock.c:30
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
void DPRINT(...)
Definition: polytest.cpp:61
FAST_MUTEX
Definition: extypes.h:17
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NO_OPLOCK
Definition: oplock.c:15
_SEH2_END
Definition: create.c:4424
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_SEH2_FINALLY
Definition: create.c:4395
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
ULONG Flags
Definition: oplock.c:42

Referenced by FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

◆ FsRtlCancelExclusiveIrp()

VOID NTAPI FsRtlCancelExclusiveIrp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 586 of file oplock.c.

588 {
589  PINTERNAL_OPLOCK IntOplock;
590  PLIST_ENTRY NextEntry;
591  PWAIT_CONTEXT WaitCtx;
592 
593  DPRINT("FsRtlCancelExclusiveIrp(%p, %p)\n", DeviceObject, Irp);
594 
595  /* Get the associated oplock */
596  IntOplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
597 
598  /* Remove the cancel routine (us!) and release the cancel spinlock */
600  IoReleaseCancelSpinLock(Irp->CancelIrql);
601 
602  /* Acquire our internal FAST_MUTEX */
603  ExAcquireFastMutex(IntOplock->IntLock);
604  /* If we had an exclusive IRP */
605  if (IntOplock->ExclusiveIrp != NULL && IntOplock->ExclusiveIrp->Cancel)
606  {
607  /* Cancel it, and remove it from the oplock */
608  IntOplock->ExclusiveIrp->IoStatus.Status = STATUS_CANCELLED;
610  IntOplock->ExclusiveIrp = NULL;
611 
612  /* Dereference the fileobject and remove the oplock */
613  ObDereferenceObject(IntOplock->FileObject);
614  IntOplock->FileObject = NULL;
615  IntOplock->Flags = NO_OPLOCK;
616 
617  /* And complete any waiting IRP */
618  for (NextEntry = IntOplock->WaitListHead.Flink;
619  NextEntry != &IntOplock->WaitListHead;
620  NextEntry = NextEntry->Flink)
621  {
622  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
624  }
625  }
626 
627  /* Done! */
628  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
629 }
PFILE_OBJECT FileObject
Definition: oplock.c:37
PFAST_MUTEX IntLock
Definition: oplock.c:43
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY WaitListHead
Definition: oplock.c:41
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
PIRP ExclusiveIrp
Definition: oplock.c:35
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
ULONG Flags
Definition: oplock.c:42

Referenced by FsRtlRequestExclusiveOplock().

◆ FsRtlCancelOplockIIIrp()

VOID NTAPI FsRtlCancelOplockIIIrp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 313 of file oplock.c.

315 {
316  PINTERNAL_OPLOCK Oplock;
317  PLIST_ENTRY NextEntry;
318  PIRP ListIrp;
320 
321  DPRINT("FsRtlCancelOplockIIIrp(%p, %p)\n", DeviceObject, Irp);
322 
323  /* Get the associated oplock */
324  Oplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
325 
326  /* Remove the cancel routine (it's OK, we're the cancel routine! )*/
328  IoReleaseCancelSpinLock(Irp->CancelIrql);
329 
330  /* Nothing removed yet */
331  Removed = FALSE;
332  ExAcquireFastMutex(Oplock->IntLock);
333  /* Browse all the IRPs associated to the shared lock */
334  for (NextEntry = Oplock->SharedListHead.Flink;
335  NextEntry != &Oplock->SharedListHead;
336  NextEntry = NextEntry->Flink)
337  {
338  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
339 
340  /* If canceled, remove it */
341  if (ListIrp->Cancel)
342  {
343  FsRtlRemoveAndCompleteIrp(ListIrp);
344  Removed = TRUE;
345  }
346  }
347 
348  /* If no IRP left, the oplock is gone */
349  if (Removed && IsListEmpty(&Oplock->SharedListHead))
350  {
351  Oplock->Flags = NO_OPLOCK;
352  }
353  /* Don't forget to release the mutex */
354  ExReleaseFastMutex(Oplock->IntLock);
355 }
PFAST_MUTEX IntLock
Definition: oplock.c:43
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY SharedListHead
Definition: oplock.c:39
IRP
Definition: iotypes.h:2463
IoSetCancelRoutine(Irp, CancelRoutine)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:285
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
Definition: fbtusb.h:86
ULONG Flags
Definition: oplock.c:42

Referenced by FsRtlAcknowledgeOplockBreak(), and FsRtlRequestOplockII().

◆ FsRtlCancelWaitIrp()

VOID NTAPI FsRtlCancelWaitIrp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 116 of file oplock.c.

118 {
119  PINTERNAL_OPLOCK Oplock;
120  PLIST_ENTRY NextEntry;
121  PWAIT_CONTEXT WaitCtx;
122 
123  DPRINT("FsRtlCancelWaitIrp(%p, %p)\n", DeviceObject, Irp);
124 
125  /* Get the associated oplock */
126  Oplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
127 
128  /* Remove the cancel routine (we're being called!) */
130  /* And release the cancel spin lock (always locked when cancel routine is called) */
131  IoReleaseCancelSpinLock(Irp->CancelIrql);
132 
133  /* Now, remove and complete any associated waiter */
134  ExAcquireFastMutex(Oplock->IntLock);
135  for (NextEntry = Oplock->WaitListHead.Flink;
136  NextEntry != &Oplock->WaitListHead;
137  NextEntry = NextEntry->Flink)
138  {
139  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
140 
141  if (WaitCtx->Irp->Cancel)
142  {
144  }
145  }
146  ExReleaseFastMutex(Oplock->IntLock);
147 }
PFAST_MUTEX IntLock
Definition: oplock.c:43
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY WaitListHead
Definition: oplock.c:41
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
PIRP Irp
Definition: oplock.c:49

Referenced by FsRtlWaitOnIrp().

◆ FsRtlCheckOplock()

NTSTATUS NTAPI FsRtlCheckOplock ( IN POPLOCK  Oplock,
IN PIRP  Irp,
IN PVOID  Context,
IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine  OPTIONAL,
IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine  OPTIONAL 
)

Definition at line 1172 of file oplock.c.

1177 {
1178  PINTERNAL_OPLOCK IntOplock;
1179  PIO_STACK_LOCATION Stack;
1183 
1184 #define BreakToIIIfRequired \
1185  if (IntOplock->Flags != LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
1186  return FsRtlOplockBreakToII(IntOplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine)
1187 
1188 #define BreakToNoneIfRequired \
1189  if (IntOplock->Flags == LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
1190  return FsRtlOplockBreakToNone(IntOplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine)
1191 
1192  DPRINT("FsRtlCheckOplock(%p, %p, %p, %p, %p)\n", Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine);
1193 
1194  IntOplock = *Oplock;
1195 
1196  /* No oplock, easy! */
1197  if (IntOplock == NULL)
1198  {
1199  return STATUS_SUCCESS;
1200  }
1201 
1202  /* No sense on paging */
1203  if (Irp->Flags & IRP_PAGING_IO)
1204  {
1205  return STATUS_SUCCESS;
1206  }
1207 
1208  /* No oplock, easy (bis!) */
1209  if (IntOplock->Flags == NO_OPLOCK)
1210  {
1211  return STATUS_SUCCESS;
1212  }
1213 
1215 
1216  /* If cleanup, cleanup the associated oplock & return */
1217  if (Stack->MajorFunction == IRP_MJ_CLEANUP)
1218  {
1219  FsRtlOplockCleanup(IntOplock, Stack);
1220  return STATUS_SUCCESS;
1221  }
1222  else if (Stack->MajorFunction == IRP_MJ_LOCK_CONTROL)
1223  {
1224  /* OK for filter */
1225  if (BooleanFlagOn(IntOplock->Flags, FILTER_OPLOCK))
1226  {
1227  return STATUS_SUCCESS;
1228  }
1229 
1230  /* Lock operation, we will have to break to no lock if shared or not us */
1232 
1233  return STATUS_SUCCESS;
1234  }
1235  else if (Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
1236  {
1237  /* FSCTL should be safe, unless user wants a write FSCTL */
1238  if (Stack->Parameters.FileSystemControl.FsControlCode != FSCTL_SET_ZERO_DATA)
1239  {
1240  return STATUS_SUCCESS;
1241  }
1242 
1243  /* We will have to break for write if shared or not us! */
1245 
1246  return STATUS_SUCCESS;
1247  }
1248  else if (Stack->MajorFunction == IRP_MJ_WRITE)
1249  {
1250  /* Write operation, we will have to break if shared or not us */
1252 
1253  return STATUS_SUCCESS;
1254  }
1255  else if (Stack->MajorFunction == IRP_MJ_READ)
1256  {
1257  /* If that's filter oplock, it's alright */
1258  if (BooleanFlagOn(IntOplock->Flags, FILTER_OPLOCK))
1259  {
1260  return STATUS_SUCCESS;
1261  }
1262 
1263  /* Otherwise, we need to break to shared oplock */
1265 
1266  return STATUS_SUCCESS;
1267  }
1268  else if (Stack->MajorFunction == IRP_MJ_CREATE)
1269  {
1270  DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess;
1271 
1272  /* If that's just for reading, the oplock is fine */
1275  {
1276  return STATUS_SUCCESS;
1277  }
1278 
1279  /* Otherwise, check the disposition */
1280  CreateDisposition = (Stack->Parameters.Create.Options >> 24) & 0x000000FF;
1284  {
1285  /* Not us, we have to break the oplock! */
1287 
1288  return STATUS_SUCCESS;
1289  }
1290 
1291  /* It's fine, we can have the oplock shared */
1293 
1294  return STATUS_SUCCESS;
1295  }
1296  else if (Stack->MajorFunction == IRP_MJ_FLUSH_BUFFERS)
1297  {
1298  /* We need to share the lock, if not done yet! */
1300 
1301  return STATUS_SUCCESS;
1302  }
1303  else if (Stack->MajorFunction == IRP_MJ_SET_INFORMATION)
1304  {
1305  /* Only deal with really specific classes */
1306  FileInfo = Stack->Parameters.SetFile.FileInformationClass;
1309  {
1310  /* No need to break */
1311  if (!BooleanFlagOn(IntOplock->Flags, (FILTER_OPLOCK | BATCH_OPLOCK)))
1312  {
1313  return STATUS_SUCCESS;
1314  }
1315  /* Otherwise break to none */
1316  else
1317  {
1319 
1320  return STATUS_SUCCESS;
1321  }
1322  }
1323  else if (FileInfo == FileAllocationInformation)
1324  {
1326 
1327  return STATUS_SUCCESS;
1328  }
1329  else if (FileInfo == FileEndOfFileInformation)
1330  {
1331  /* Advance only, nothing to do */
1332  if (Stack->Parameters.SetFile.AdvanceOnly)
1333  {
1334  return STATUS_SUCCESS;
1335  }
1336 
1337  /* Otherwise, attempt to break to none */
1339 
1340  return STATUS_SUCCESS;
1341  }
1342  }
1343 
1344 #undef BreakToIIIfRequired
1345 #undef BreakToNoneIfRequired
1346 
1347  return STATUS_SUCCESS;
1348 }
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BATCH_OPLOCK
Definition: oplock.c:17
#define IRP_MJ_FLUSH_BUFFERS
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FILTER_OPLOCK
Definition: oplock.c:18
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define BreakToIIIfRequired
#define FILE_RESERVE_OPFILTER
Definition: from_kernel.h:45
#define FSCTL_SET_ZERO_DATA
Definition: winioctl.h:141
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:125
#define FILE_READ_DATA
Definition: nt_native.h:628
smooth NULL
Definition: ftsmooth.c:416
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
void DPRINT(...)
Definition: polytest.cpp:61
#define FILE_WRITE_DATA
Definition: nt_native.h:631
VOID FsRtlOplockCleanup(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack)
Definition: oplock.c:818
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define READ_CONTROL
Definition: nt_native.h:58
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_EXECUTE
Definition: nt_native.h:642
#define BreakToNoneIfRequired
#define SYNCHRONIZE
Definition: nt_native.h:61
#define NO_OPLOCK
Definition: oplock.c:15
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
#define FILE_READ_EA
Definition: nt_native.h:638
#define IRP_PAGING_IO
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_CLEANUP
struct FileInfo FileInfo
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
unsigned int ULONG
Definition: retypes.h:1
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2938
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT _In_ ULONG CreateDisposition
Definition: create.c:4157
HRESULT Create([out]ITransactionReceiver **ppReceiver)
ULONG ACCESS_MASK
Definition: nt_native.h:40
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673
ULONG Flags
Definition: oplock.c:42

Referenced by _Dispatch_type_(), _Requires_lock_held_(), CdCommonLockControl(), Ext2Cleanup(), Ext2CreateFile(), Ext2LockControl(), Ext2ReadFile(), Ext2SetFileInformation(), Ext2WriteFile(), FatSetRenameInfo(), fsctl_request(), and open_file2().

◆ FsRtlCompletionRoutinePriv()

VOID NTAPI FsRtlCompletionRoutinePriv ( IN PVOID  Context,
IN PIRP  Irp 
)

Definition at line 71 of file oplock.c.

73 {
74  PKEVENT WaitEvent;
75 
76  PAGED_CODE();
77 
78  DPRINT("FsRtlCompletionRoutinePriv(%p, %p)\n", Context, Irp);
79 
80  /* Set the event */
81  WaitEvent = (PKEVENT)Context;
82  KeSetEvent(WaitEvent, IO_NO_INCREMENT, FALSE);
83 }
struct _KEVENT * PKEVENT
_In_ PIRP Irp
Definition: csq.h:116
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define PAGED_CODE()
Definition: video.h:57
void DPRINT(...)
Definition: polytest.cpp:61
#define IO_NO_INCREMENT
Definition: iotypes.h:566

Referenced by FsRtlWaitOnIrp().

◆ FsRtlCurrentBatchOplock()

BOOLEAN NTAPI FsRtlCurrentBatchOplock ( IN POPLOCK  Oplock)

Definition at line 1366 of file oplock.c.

1367 {
1368  PINTERNAL_OPLOCK IntOplock;
1369 
1370  PAGED_CODE();
1371 
1372  DPRINT("FsRtlCurrentBatchOplock(%p)\n", Oplock);
1373 
1374  IntOplock = *Oplock;
1375 
1376  /* Only return true if batch or filter oplock */
1377  if (IntOplock != NULL &&
1378  BooleanFlagOn(IntOplock->Flags, (FILTER_OPLOCK | BATCH_OPLOCK)))
1379  {
1380  return TRUE;
1381  }
1382 
1383  return FALSE;
1384 }
#define TRUE
Definition: types.h:120
#define BATCH_OPLOCK
Definition: oplock.c:17
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FILTER_OPLOCK
Definition: oplock.c:18
#define PAGED_CODE()
Definition: video.h:57
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
ULONG Flags
Definition: oplock.c:42

Referenced by Ext2CreateFile(), and FatSetRenameInfo().

◆ FsRtlInitializeOplock()

VOID NTAPI FsRtlInitializeOplock ( IN OUT POPLOCK  Oplock)

Definition at line 1402 of file oplock.c.

1403 {
1404  PAGED_CODE();
1405 
1406  /* Nothing to do */
1407  DPRINT("FsRtlInitializeOplock(%p)\n", Oplock);
1408 }
#define PAGED_CODE()
Definition: video.h:57
void DPRINT(...)
Definition: polytest.cpp:61

Referenced by CdCreateFcb(), create_fcb(), Ext2AllocateFcb(), FatCreateDcb(), and FatCreateFcb().

◆ FsRtlNotifyCompletion()

VOID NTAPI FsRtlNotifyCompletion ( IN PVOID  Context,
IN PIRP  Irp 
)

Definition at line 58 of file oplock.c.

60 {
61  PAGED_CODE();
62 
63  DPRINT("FsRtlNotifyCompletion(%p, %p)\n", Context, Irp);
64 
65  /* Just complete the IRP */
67 }
_In_ PIRP Irp
Definition: csq.h:116
#define PAGED_CODE()
Definition: video.h:57
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61

Referenced by FsRtlOplockBreakNotify().

◆ FsRtlOpBatchBreakClosePending()

NTSTATUS FsRtlOpBatchBreakClosePending ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp 
)

Definition at line 472 of file oplock.c.

475 {
477  PLIST_ENTRY NextEntry;
478  PWAIT_CONTEXT WaitCtx;
479 
480  PAGED_CODE();
481 
482  DPRINT("FsRtlOpBatchBreakClosePending(%p, %p, %p)\n", Oplock, Stack, Irp);
483 
484  /* No oplock, that's not legit! */
485  if (Oplock == NULL)
486  {
487  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
490  }
491 
493  ExAcquireFastMutexUnsafe(Oplock->IntLock);
494 
495  /* First of all, check if all conditions are met:
496  * Correct FO + broken oplock
497  */
498  if (Oplock->FileObject == Stack->FileObject && (BooleanFlagOn(Oplock->Flags, (BROKEN_TO_LEVEL_2 | BROKEN_TO_NONE | BROKEN_TO_NONE_FROM_LEVEL_2))))
499  {
500  /* If we have a pending or level 1 oplock... */
501  if (BooleanFlagOn(Oplock->Flags, (PENDING_LOCK | LEVEL_1_OPLOCK)))
502  {
503  /* Remove our extra ref from the FO */
504  if (Oplock->Flags & LEVEL_1_OPLOCK)
505  {
506  ObDereferenceObject(Oplock->FileObject);
507  }
508 
509  /* And remove the oplock */
510  Oplock->Flags = NO_OPLOCK;
511  Oplock->FileObject = NULL;
512 
513  /* Complete any waiting IRP */
514  for (NextEntry = Oplock->WaitListHead.Flink;
515  NextEntry != &Oplock->WaitListHead;
516  NextEntry = NextEntry->Flink)
517  {
518  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
520  }
521  }
522  /* Otherwise, mark the oplock as close pending */
523  else
524  {
525  ClearFlag(Oplock->Flags, BROKEN_ANY);
526  SetFlag(Oplock->Flags, BROKEN_TO_CLOSE_PENDING);
527  }
528  }
529  /* Oplock is in invalid state */
530  else
531  {
533  }
534 
535  /* And complete */
536  Irp->IoStatus.Status = Status;
538  ExReleaseFastMutexUnsafe(Oplock->IntLock);
539 
540  return Status;
541 }
#define PENDING_LOCK
Definition: oplock.c:22
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_OPLOCK_PROTOCOL
Definition: ntstatus.h:449
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define BROKEN_TO_NONE
Definition: oplock.c:25
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define PAGED_CODE()
Definition: video.h:57
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define BROKEN_ANY
Definition: oplock.c:28
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define BROKEN_TO_CLOSE_PENDING
Definition: oplock.c:27
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:117
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
#define NO_OPLOCK
Definition: oplock.c:15
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by FsRtlOplockFsctrl().

◆ FsRtlOplockBreakNotify()

NTSTATUS FsRtlOplockBreakNotify ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp 
)

Definition at line 241 of file oplock.c.

244 {
245  PAGED_CODE();
246 
247  DPRINT("FsRtlOplockBreakNotify(%p, %p, %p)\n", Oplock, Stack, Irp);
248 
249  /* No oplock, no break to notify */
250  if (Oplock == NULL)
251  {
252  Irp->IoStatus.Status = STATUS_SUCCESS;
254  return STATUS_SUCCESS;
255  }
256 
257  /* Notify by completing the IRP, unless we have broken to shared */
258  ExAcquireFastMutexUnsafe(Oplock->IntLock);
259  if (!BooleanFlagOn(Oplock->Flags, BROKEN_TO_LEVEL_2))
260  {
261  Irp->IoStatus.Status = STATUS_SUCCESS;
263  ExReleaseFastMutexUnsafe(Oplock->IntLock);
264  return STATUS_SUCCESS;
265  }
266 
267  /* If it's pending, just complete the IRP and get rid of the oplock */
268  if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
269  {
270  Oplock->FileObject = NULL;
271  Oplock->Flags = NO_OPLOCK;
272  Irp->IoStatus.Status = STATUS_SUCCESS;
274  ExReleaseFastMutexUnsafe(Oplock->IntLock);
275  return STATUS_SUCCESS;
276  }
277 
278  /* Otherwise, wait on the IRP */
279  Irp->IoStatus.Status = STATUS_SUCCESS;
281  return STATUS_SUCCESS;
282 }
#define PENDING_LOCK
Definition: oplock.c:22
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define PAGED_CODE()
Definition: video.h:57
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
VOID FsRtlWaitOnIrp(IN PINTERNAL_OPLOCK Oplock, IN PIRP Irp, IN PVOID CompletionContext, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine, IN PKEVENT WaitEvent)
Definition: oplock.c:150
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
#define NO_OPLOCK
Definition: oplock.c:15
return STATUS_SUCCESS
Definition: btrfs.c:2938
VOID NTAPI FsRtlNotifyCompletion(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:58

Referenced by FsRtlOplockFsctrl().

◆ FsRtlOplockBreakToII()

NTSTATUS NTAPI FsRtlOplockBreakToII ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp,
IN PVOID  Context,
IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine  OPTIONAL,
IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine  OPTIONAL 
)

Definition at line 1037 of file oplock.c.

1043 {
1044  PLIST_ENTRY NextEntry;
1045  PWAIT_CONTEXT WaitCtx;
1046  KEVENT WaitEvent;
1047 
1048  DPRINT("FsRtlOplockBreakToII(%p, %p, %p, %p, %p, %p)\n", Oplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine);
1049 
1050  ExAcquireFastMutexUnsafe(Oplock->IntLock);
1051 
1052  /* If our lock, or if not exclusively locked, nothing to break! */
1053  if (!BooleanFlagOn(Oplock->Flags, EXCLUSIVE_LOCK) || Oplock->FileObject == Stack->FileObject)
1054  {
1055  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1056  return STATUS_SUCCESS;
1057  }
1058 
1059  /* If already broken or not set yet */
1060  if (BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK)))
1061  {
1062  /* Drop oplock if pending */
1063  if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
1064  {
1065  Oplock->Flags = NO_OPLOCK;
1066  Oplock->FileObject = NULL;
1067 
1068  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1069  return STATUS_SUCCESS;
1070  }
1071 
1072  }
1073  /* To break! */
1074  else
1075  {
1076  /* Drop the cancel routine of the exclusive IRP */
1077  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
1078  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
1079  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
1080 
1081  /* If it was canceled in between, break to no oplock */
1082  if (Oplock->ExclusiveIrp->Cancel)
1083  {
1084  /* Complete the IRP with cancellation */
1085  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1086  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_CANCELLED;
1087  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
1088 
1089  /* And mark we have no longer lock */
1090  Oplock->Flags = NO_OPLOCK;
1091  Oplock->ExclusiveIrp = NULL;
1092  ObDereferenceObject(Oplock->FileObject);
1093  Oplock->FileObject = NULL;
1094 
1095  /* Finally, complete any waiter */
1096  for (NextEntry = Oplock->WaitListHead.Flink;
1097  NextEntry != &Oplock->WaitListHead;
1098  NextEntry = NextEntry->Flink)
1099  {
1100  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
1102  }
1103 
1104  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1105 
1106  return STATUS_SUCCESS;
1107  }
1108 
1109  /* It wasn't canceled, so break to shared unless we were alone, in that case we break to no lock! */
1110  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
1111  if (BooleanFlagOn(Oplock->Flags, (BATCH_OPLOCK | LEVEL_1_OPLOCK)))
1112  {
1113  SetFlag(Oplock->Flags, BROKEN_TO_LEVEL_2);
1114  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_LEVEL_2;
1115  }
1116  else
1117  {
1118  SetFlag(Oplock->Flags, BROKEN_TO_NONE);
1119  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1120  }
1121  /* And complete */
1122  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
1123  Oplock->ExclusiveIrp = NULL;
1124  }
1125 
1126  /* Wait if required */
1127  if (Stack->MajorFunction != IRP_MJ_CREATE || !BooleanFlagOn(Stack->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED))
1128  {
1129  FsRtlWaitOnIrp(Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine, &WaitEvent);
1130 
1131  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1132 
1133  return STATUS_SUCCESS;
1134  }
1135  else
1136  {
1137  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1139  }
1140 }
#define PENDING_LOCK
Definition: oplock.c:22
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BATCH_OPLOCK
Definition: oplock.c:17
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define FILE_OPLOCK_BROKEN_TO_LEVEL_2
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define BROKEN_TO_NONE
Definition: oplock.c:25
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
VOID FsRtlWaitOnIrp(IN PINTERNAL_OPLOCK Oplock, IN PIRP Irp, IN PVOID CompletionContext, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine, IN PKEVENT WaitEvent)
Definition: oplock.c:150
#define BROKEN_ANY
Definition: oplock.c:28
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
#define EXCLUSIVE_LOCK
Definition: oplock.c:21
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673

◆ FsRtlOplockBreakToNone()

NTSTATUS NTAPI FsRtlOplockBreakToNone ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp,
IN PVOID  Context,
IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine  OPTIONAL,
IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine  OPTIONAL 
)

Definition at line 903 of file oplock.c.

909 {
910  PLIST_ENTRY NextEntry;
911  PWAIT_CONTEXT WaitCtx;
912  PIRP ListIrp;
913  KEVENT WaitEvent;
914 
915  DPRINT("FsRtlOplockBreakToNone(%p, %p, %p, %p, %p, %p)\n", Oplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine);
916 
917  ExAcquireFastMutexUnsafe(Oplock->IntLock);
918 
919  /* No oplock to break! */
920  if (Oplock->Flags == NO_OPLOCK)
921  {
922  ExReleaseFastMutexUnsafe(Oplock->IntLock);
923  return STATUS_SUCCESS;
924  }
925 
926  /* Not broken yet, but set... Let's do it!
927  * Also, we won't break a shared oplock
928  */
929  if (!BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK | LEVEL_2_OPLOCK)))
930  {
931  /* Remove our cancel routine, no longer needed */
932  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
933  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
934  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
935 
936  /* If the IRP got canceled, we need to cleanup a bit */
937  if (Oplock->ExclusiveIrp->Cancel)
938  {
939  /* Return cancelation */
940  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
941  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_CANCELLED;
942  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
943 
944  /* No oplock left */
945  Oplock->Flags = NO_OPLOCK;
946  Oplock->ExclusiveIrp = NULL;
947 
948  /* No need for the FO anymore */
949  ObDereferenceObject(Oplock->FileObject);
950  Oplock->FileObject = NULL;
951 
952  /* And complete any waiting IRP */
953  for (NextEntry = Oplock->WaitListHead.Flink;
954  NextEntry != &Oplock->WaitListHead;
955  NextEntry = NextEntry->Flink)
956  {
957  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
959  }
960 
961  /* Done! */
962  ExReleaseFastMutexUnsafe(Oplock->IntLock);
963 
964  return STATUS_SUCCESS;
965  }
966 
967  /* Easier break, just complete :-) */
968  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
969  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
970  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
971 
972  /* And remove our exclusive IRP */
973  Oplock->ExclusiveIrp = NULL;
974  SetFlag(Oplock->Flags, BROKEN_TO_NONE);
975  }
976  /* Shared lock */
977  else if (Oplock->Flags == LEVEL_2_OPLOCK)
978  {
979  /* Complete any IRP in the shared lock */
980  for (NextEntry = Oplock->SharedListHead.Flink;
981  NextEntry != &Oplock->SharedListHead;
982  NextEntry = NextEntry->Flink)
983  {
984  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
985  FsRtlRemoveAndCompleteIrp(ListIrp);
986  }
987 
988  /* No lock left */
989  Oplock->Flags = NO_OPLOCK;
990 
991  /* Done */
992  ExReleaseFastMutexUnsafe(Oplock->IntLock);
993  return STATUS_SUCCESS;
994  }
995  /* If it was broken to level 2, break it to none from level 2 */
996  else if (Oplock->Flags & BROKEN_TO_LEVEL_2)
997  {
998  ClearFlag(Oplock->Flags, BROKEN_TO_LEVEL_2);
999  SetFlag(Oplock->Flags, BROKEN_TO_NONE_FROM_LEVEL_2);
1000  }
1001  /* If it was pending, just drop the lock */
1002  else if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
1003  {
1004  Oplock->Flags = NO_OPLOCK;
1005  Oplock->FileObject = NULL;
1006 
1007  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1008  return STATUS_SUCCESS;
1009  }
1010 
1011  /* If that's ours, job done */
1012  if (Oplock->FileObject == Stack->FileObject)
1013  {
1014  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1015  return STATUS_SUCCESS;
1016  }
1017 
1018  /* Otherwise, wait on the IRP */
1019  if (Stack->MajorFunction != IRP_MJ_CREATE || !BooleanFlagOn(Stack->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED))
1020  {
1021  FsRtlWaitOnIrp(Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine, &WaitEvent);
1022 
1023  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1024 
1025  return STATUS_SUCCESS;
1026  }
1027  /* Done */
1028  else
1029  {
1030  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1032  }
1033 }
#define PENDING_LOCK
Definition: oplock.c:22
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
_In_ PIRP Irp
Definition: csq.h:116
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
IRP
Definition: iotypes.h:2463
#define BROKEN_TO_NONE
Definition: oplock.c:25
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
VOID FsRtlWaitOnIrp(IN PINTERNAL_OPLOCK Oplock, IN PIRP Irp, IN PVOID CompletionContext, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine, IN PKEVENT WaitEvent)
Definition: oplock.c:150
#define BROKEN_ANY
Definition: oplock.c:28
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:285
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:117
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673

◆ FsRtlOplockCleanup()

VOID FsRtlOplockCleanup ( IN PINTERNAL_OPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack 
)

Definition at line 818 of file oplock.c.

820 {
821  PIO_STACK_LOCATION ListStack;
822  PLIST_ENTRY NextEntry;
823  PIRP ListIrp;
824  PWAIT_CONTEXT WaitCtx;
825 
826  DPRINT("FsRtlOplockCleanup(%p, %p)\n", Oplock, Stack);
827 
828  ExAcquireFastMutexUnsafe(Oplock->IntLock);
829  /* oplock cleaning only makes sense if there's an oplock */
830  if (Oplock->Flags != NO_OPLOCK)
831  {
832  /* Shared lock */
833  if (Oplock->Flags == LEVEL_2_OPLOCK)
834  {
835  /* Complete any associated IRP */
836  for (NextEntry = Oplock->SharedListHead.Flink;
837  NextEntry != &Oplock->SharedListHead;
838  NextEntry = NextEntry->Flink)
839  {
840  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
841  ListStack = IoGetCurrentIrpStackLocation(ListIrp);
842 
843  if (Stack->FileObject == ListStack->FileObject)
844  {
845  FsRtlRemoveAndCompleteIrp(ListIrp);
846  }
847  }
848 
849  /* If, in the end, no IRP is left, then the lock is gone */
850  if (IsListEmpty(&Oplock->SharedListHead))
851  {
852  Oplock->Flags = NO_OPLOCK;
853  }
854  }
855  else
856  {
857  /* If we have matching file */
858  if (Oplock->FileObject == Stack->FileObject)
859  {
860  /* Oplock wasn't broken (still exclusive), easy case */
861  if (!BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK)))
862  {
863  /* Remove the cancel routine we set previously */
864  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
865  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
866  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
867 
868  /* And return the fact we broke the oplock to no oplock */
869  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
870  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
871 
872  /* And complete! */
873  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
874  Oplock->ExclusiveIrp = NULL;
875  }
876 
877  /* If no pending, we can safely dereference the file object */
878  if (!BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
879  {
880  ObDereferenceObject(Oplock->FileObject);
881  }
882 
883  /* Now, remove the oplock */
884  Oplock->FileObject = NULL;
885  Oplock->Flags = NO_OPLOCK;
886 
887  /* And complete any waiting IRP */
888  for (NextEntry = Oplock->WaitListHead.Flink;
889  NextEntry != &Oplock->WaitListHead;
890  NextEntry = NextEntry->Flink)
891  {
892  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
894  }
895  }
896  }
897  }
898  ExReleaseFastMutexUnsafe(Oplock->IntLock);
899 }
#define PENDING_LOCK
Definition: oplock.c:22
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
IRP
Definition: iotypes.h:2463
IoSetCancelRoutine(Irp, CancelRoutine)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
#define BROKEN_ANY
Definition: oplock.c:28
smooth NULL
Definition: ftsmooth.c:416
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:86
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:285
Definition: typedefs.h:117
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by FsRtlCheckOplock().

◆ FsRtlOplockFsctrl()

NTSTATUS NTAPI FsRtlOplockFsctrl ( IN POPLOCK  Oplock,
IN PIRP  Irp,
IN ULONG  OpenCount 
)

Definition at line 1432 of file oplock.c.

1435 {
1436  PIO_STACK_LOCATION Stack;
1437  PINTERNAL_OPLOCK IntOplock;
1438 
1439  PAGED_CODE();
1440 
1441  DPRINT("FsRtlOplockFsctrl(%p, %p, %lu)\n", Oplock, Irp, OpenCount);
1442 
1443  IntOplock = *Oplock;
1445  /* Make sure it's not called on create */
1446  if (Stack->MajorFunction != IRP_MJ_CREATE)
1447  {
1448  switch (Stack->Parameters.FileSystemControl.FsControlCode)
1449  {
1451  return FsRtlOplockBreakNotify(IntOplock, Stack, Irp);
1452 
1454  return FsRtlAcknowledgeOplockBreak(IntOplock, Stack, Irp, FALSE);
1455 
1457  return FsRtlOpBatchBreakClosePending(IntOplock, Stack, Irp);
1458 
1460  /* We can only grant level 1 if synchronous, and only a single handle to it
1461  * (plus, not a paging IO - obvious, and not cleanup done...)
1462  */
1463  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1465  {
1467  }
1468  /* Not matching, fail */
1469  else
1470  {
1471  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1474  }
1475 
1477  /* Shared can only be granted if no byte-range lock, and async operation
1478  * (plus, not a paging IO - obvious, and not cleanup done...)
1479  */
1480  if (OpenCount == 0 && !IoIsOperationSynchronous(Irp) &&
1482  {
1483  return FsRtlRequestOplockII(Oplock, Stack, Irp);
1484  }
1485  /* Not matching, fail */
1486  else
1487  {
1488  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1491  }
1492 
1494  return FsRtlAcknowledgeOplockBreak(IntOplock, Stack, Irp, TRUE);
1495 
1497  /* Batch oplock can only be granted if there's a byte-range lock and async operation
1498  * (plus, not a paging IO - obvious, and not cleanup done...)
1499  */
1500  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1502  {
1503  return FsRtlRequestExclusiveOplock(Oplock, Stack, Irp, EXCLUSIVE_LOCK | BATCH_OPLOCK);
1504  }
1505  /* Not matching, fail */
1506  else
1507  {
1508  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1511  }
1512 
1514  /* Filter oplock can only be granted if there's a byte-range lock and async operation
1515  * (plus, not a paging IO - obvious, and not cleanup done...)
1516  */
1517  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1519  {
1520  return FsRtlRequestExclusiveOplock(Oplock, Stack, Irp, EXCLUSIVE_LOCK | FILTER_OPLOCK);
1521  }
1522  /* Not matching, fail */
1523  else
1524  {
1525  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1528  }
1529 
1530  default:
1531  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1533  return STATUS_INVALID_PARAMETER;
1534  }
1535  }
1536 
1537  /* That's a create operation! Only grant exclusive if there's a single user handle opened
1538  * and we're only performing reading operations.
1539  */
1540  if (OpenCount == 1 &&
1541  !(Stack->Parameters.Create.SecurityContext->DesiredAccess & ~(FILE_READ_ATTRIBUTES | FILE_READ_DATA)) &&
1543  {
1545  }
1546 
1548 }
#define TRUE
Definition: types.h:120
#define PENDING_LOCK
Definition: oplock.c:22
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BATCH_OPLOCK
Definition: oplock.c:17
NTSTATUS FsRtlOpBatchBreakClosePending(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:472
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FILTER_OPLOCK
Definition: oplock.c:18
NTSTATUS FsRtlAcknowledgeOplockBreak(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN BOOLEAN SwitchToLevel2)
Definition: oplock.c:358
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define PAGED_CODE()
Definition: video.h:57
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSTATUS FsRtlOplockBreakNotify(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:241
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:448
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
NTSTATUS FsRtlRequestOplockII(IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:736
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
NTSTATUS FsRtlRequestExclusiveOplock(IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN ULONG Flags)
Definition: oplock.c:632
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FILE_SHARE_VALID_FLAGS
Definition: nt_native.h:683
#define EXCLUSIVE_LOCK
Definition: oplock.c:21
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1747
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
DWORD OpenCount
Definition: legacy.c:25
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
HRESULT Create([out]ITransactionReceiver **ppReceiver)
#define IRP_SYNCHRONOUS_PAGING_IO

Referenced by Ext2OplockRequest(), fsctl_oplock(), and if().

◆ FsRtlOplockIsFastIoPossible()

BOOLEAN NTAPI FsRtlOplockIsFastIoPossible ( IN POPLOCK  Oplock)

Definition at line 1566 of file oplock.c.

1567 {
1568  PINTERNAL_OPLOCK IntOplock;
1569 
1570  PAGED_CODE();
1571 
1572  DPRINT("FsRtlOplockIsFastIoPossible(%p)\n", Oplock);
1573 
1574  IntOplock = *Oplock;
1575 
1576  /* If there's a shared oplock or if it was used for write operation, deny FastIO */
1577  if (IntOplock != NULL &&
1578  BooleanFlagOn(IntOplock->Flags, (BROKEN_ANY | LEVEL_2_OPLOCK)))
1579  {
1580  return FALSE;
1581  }
1582 
1583  return TRUE;
1584 }
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define PAGED_CODE()
Definition: video.h:57
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
#define BROKEN_ANY
Definition: oplock.c:28
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
ULONG Flags
Definition: oplock.c:42

Referenced by _Function_class_(), CdFastLock(), CdFastUnlockAll(), CdFastUnlockAllByKey(), CdFastUnlockSingle(), Ext2FastIoLock(), Ext2FastIoUnlockAll(), Ext2FastIoUnlockAllByKey(), Ext2FastIoUnlockSingle(), Ext2IsFastIoPossible(), and fast_io_possible().

◆ FsRtlRemoveAndCompleteIrp()

VOID FsRtlRemoveAndCompleteIrp ( IN PIRP  Irp)

Definition at line 285 of file oplock.c.

286 {
287  PIO_STACK_LOCATION Stack;
288 
289  DPRINT("FsRtlRemoveAndCompleteIrp(%p)\n", Irp);
290 
292 
293  /* Remove our extra ref */
295 
296  /* Remove our cancel routine */
297  IoAcquireCancelSpinLock(&Irp->CancelIrql);
299  IoReleaseCancelSpinLock(Irp->CancelIrql);
300 
301  /* Remove the IRP from the list it may be in (wait or shared) */
302  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
303 
304  /* And complete! */
305  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
306  Irp->IoStatus.Status = (Irp->Cancel ? STATUS_CANCELLED : STATUS_SUCCESS);
307 
309 }
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
IoSetCancelRoutine(Irp, CancelRoutine)
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by FsRtlCancelOplockIIIrp(), FsRtlOplockBreakToNone(), FsRtlOplockCleanup(), and FsRtlRequestExclusiveOplock().

◆ FsRtlRemoveAndCompleteWaitIrp()

VOID FsRtlRemoveAndCompleteWaitIrp ( IN PWAIT_CONTEXT  WaitCtx)

Definition at line 86 of file oplock.c.

87 {
88  PIRP Irp;
89 
90  PAGED_CODE();
91 
92  DPRINT("FsRtlRemoveAndCompleteWaitIrp(%p)\n", WaitCtx);
93 
94  RemoveEntryList(&WaitCtx->WaitListEntry);
95  Irp = WaitCtx->Irp;
96 
97  /* No cancel routine anymore */
98  IoAcquireCancelSpinLock(&Irp->CancelIrql);
100  IoReleaseCancelSpinLock(Irp->CancelIrql);
101 
102  /* Set the information */
103  Irp->IoStatus.Information = WaitCtx->SavedInformation;
104  /* Set the status according to the fact it got cancel or not */
105  Irp->IoStatus.Status = (Irp->Cancel ? STATUS_CANCELLED : STATUS_SUCCESS);
106 
107  /* Call the completion routine */
108  WaitCtx->CompletionRoutine(WaitCtx->CompletionContext, Irp);
109 
110  /* And get rid of the now useless wait context */
111  ExFreePoolWithTag(WaitCtx, TAG_OPLOCK);
112 }
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define TAG_OPLOCK
Definition: oplock.c:30
IoSetCancelRoutine(Irp, CancelRoutine)
#define PAGED_CODE()
Definition: video.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by FsRtlAcknowledgeOplockBreak(), FsRtlCancelExclusiveIrp(), FsRtlCancelWaitIrp(), FsRtlOpBatchBreakClosePending(), FsRtlOplockBreakToII(), FsRtlOplockBreakToNone(), and FsRtlOplockCleanup().

◆ FsRtlRequestExclusiveOplock()

NTSTATUS FsRtlRequestExclusiveOplock ( IN POPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp,
IN ULONG  Flags 
)

Definition at line 632 of file oplock.c.

636 {
637  PINTERNAL_OPLOCK IntOplock;
638  PIRP ListIrp;
639  BOOLEAN Locked;
641 
642  DPRINT("FsRtlRequestExclusiveOplock(%p, %p, %p, %lu)\n", Oplock, Stack, Irp, Flags);
643 
644  IntOplock = *Oplock;
645  Locked = FALSE;
647 
648  /* Time to work! */
649  _SEH2_TRY
650  {
651  /* Was the oplock already allocated? If not, do it now! */
652  if (IntOplock == NULL)
653  {
654  *Oplock = FsRtlAllocateOplock();
655  IntOplock = *Oplock;
656  }
657 
658  /* Acquire our internal lock */
659  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
660  Locked = TRUE;
661 
662  /* If we request exclusiveness, a filter or a pending oplock, grant it */
664  {
665  /* Either no oplock, or pending */
666  ASSERT(BooleanFlagOn(IntOplock->Flags, (NO_OPLOCK | PENDING_LOCK)));
667  IntOplock->ExclusiveIrp = Irp;
668  IntOplock->FileObject = Stack->FileObject;
669  IntOplock->Flags = (EXCLUSIVE_LOCK | PENDING_LOCK | FILTER_OPLOCK);
670  }
671  else
672  {
673  /* Otherwise, shared or no effective oplock */
675  {
676  /* The shared IRPs list should contain a single entry! */
677  if (IntOplock->Flags == LEVEL_2_OPLOCK)
678  {
679  ListIrp = CONTAINING_RECORD(IntOplock->SharedListHead.Flink, IRP, Tail.Overlay.ListEntry);
680  ASSERT(IntOplock->SharedListHead.Flink == IntOplock->SharedListHead.Blink);
681  FsRtlRemoveAndCompleteIrp(ListIrp);
682  }
683 
684  /* Set the exclusiveness */
685  IntOplock->ExclusiveIrp = Irp;
686  IntOplock->FileObject = Stack->FileObject;
687  IntOplock->Flags = Flags;
688 
689  /* Mark the IRP pending and reference our file object */
691  ObReferenceObject(Stack->FileObject);
692  Irp->IoStatus.Information = (ULONG_PTR)IntOplock;
693 
694  /* Now, set ourselves as cancel routine */
695  IoAcquireCancelSpinLock(&Irp->CancelIrql);
696  /* Unless IRP got canceled, then, just give up */
697  if (Irp->Cancel)
698  {
699  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
700  Locked = FALSE;
703  }
704  else
705  {
707  IoReleaseCancelSpinLock(Irp->CancelIrql);
708  }
709  }
710  /* Cannot set exclusiveness, fail */
711  else
712  {
713  if (Irp != NULL)
714  {
715  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
718  }
719  }
720  }
721  }
722  /* If locked, release */
724  {
725  if (Locked)
726  {
727  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
728  }
729  }
730  _SEH2_END;
731 
732  return Status;
733 }
PFILE_OBJECT FileObject
Definition: oplock.c:37
PFAST_MUTEX IntLock
Definition: oplock.c:43
#define TRUE
Definition: types.h:120
#define PENDING_LOCK
Definition: oplock.c:22
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY SharedListHead
Definition: oplock.c:39
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
#define FILTER_OPLOCK
Definition: oplock.c:18
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
IRP
Definition: iotypes.h:2463
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
VOID NTAPI FsRtlCancelExclusiveIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:586
_SEH2_TRY
Definition: create.c:4250
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
PIRP ExclusiveIrp
Definition: oplock.c:35
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:448
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:285
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
#define NO_OPLOCK
Definition: oplock.c:15
#define EXCLUSIVE_LOCK
Definition: oplock.c:21
_SEH2_END
Definition: create.c:4424
_SEH2_FINALLY
Definition: create.c:4395
#define ObReferenceObject
Definition: obfuncs.h:204
#define ULONG_PTR
Definition: config.h:101
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
PINTERNAL_OPLOCK FsRtlAllocateOplock(VOID)
Definition: oplock.c:544
ULONG Flags
Definition: oplock.c:42

Referenced by FsRtlOplockFsctrl().

◆ FsRtlRequestOplockII()

NTSTATUS FsRtlRequestOplockII ( IN POPLOCK  Oplock,
IN PIO_STACK_LOCATION  Stack,
IN PIRP  Irp 
)

Definition at line 736 of file oplock.c.

739 {
740  BOOLEAN Locked;
742  PINTERNAL_OPLOCK IntOplock;
743 
744  DPRINT("FsRtlRequestOplockII(%p, %p, %p)\n", Oplock, Stack, Irp);
745 
746  IntOplock = *Oplock;
747  Locked = FALSE;
749 
750  _SEH2_TRY
751  {
752  /* No oplock yet? Allocate it */
753  if (IntOplock == NULL)
754  {
755  *Oplock = FsRtlAllocateOplock();
756  IntOplock = *Oplock;
757  }
758 
759  /* Acquire the oplock */
760  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
761  Locked = TRUE;
762 
763  /* If already shared, or no oplock that's fine! */
764  if (BooleanFlagOn(IntOplock->Flags, (LEVEL_2_OPLOCK | NO_OPLOCK)))
765  {
767  /* Granted! */
768  Irp->IoStatus.Status = STATUS_SUCCESS;
769 
770  /* Insert in the shared list */
771  InsertTailList(&IntOplock->SharedListHead, &Irp->Tail.Overlay.ListEntry);
772 
773  /* Save the associated oplock */
774  Irp->IoStatus.Information = (ULONG_PTR)IntOplock;
775 
776  /* The oplock is shared */
777  IntOplock->Flags = LEVEL_2_OPLOCK;
778 
779  /* Reference the fileobject */
780  ObReferenceObject(Stack->FileObject);
781 
782  /* Set our cancel routine, unless the IRP got canceled in-between */
783  IoAcquireCancelSpinLock(&Irp->CancelIrql);
784  if (Irp->Cancel)
785  {
786  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
787  Locked = FALSE;
790  }
791  else
792  {
794  IoReleaseCancelSpinLock(Irp->CancelIrql);
795  }
796  }
797  /* Otherwise, just fail */
798  else
799  {
800  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
803  }
804  }
806  {
807  if (Locked)
808  {
809  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
810  }
811  }
812  _SEH2_END;
813 
814  return Status;
815 }
PFAST_MUTEX IntLock
Definition: oplock.c:43
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY SharedListHead
Definition: oplock.c:39
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define InsertTailList(ListHead, Entry)
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_SEH2_TRY
Definition: create.c:4250
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:448
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
Status
Definition: gdiplustypes.h:24
#define NO_OPLOCK
Definition: oplock.c:15
_SEH2_END
Definition: create.c:4424
_SEH2_FINALLY
Definition: create.c:4395
#define ObReferenceObject
Definition: obfuncs.h:204
#define ULONG_PTR
Definition: config.h:101
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
VOID NTAPI FsRtlCancelOplockIIIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:313
PINTERNAL_OPLOCK FsRtlAllocateOplock(VOID)
Definition: oplock.c:544
ULONG Flags
Definition: oplock.c:42

Referenced by FsRtlOplockFsctrl().

◆ FsRtlUninitializeOplock()

VOID NTAPI FsRtlUninitializeOplock ( IN POPLOCK  Oplock)

Definition at line 1602 of file oplock.c.

1603 {
1604  PINTERNAL_OPLOCK IntOplock;
1605  PLIST_ENTRY NextEntry;
1606  PWAIT_CONTEXT WaitCtx;
1607  PIRP Irp;
1608  PIO_STACK_LOCATION Stack;
1609 
1610  DPRINT("FsRtlUninitializeOplock(%p)\n", Oplock);
1611 
1612  IntOplock = *Oplock;
1613 
1614  /* No oplock, nothing to do */
1615  if (IntOplock == NULL)
1616  {
1617  return;
1618  }
1619 
1620  /* Caller won't have the oplock anymore */
1621  *Oplock = NULL;
1622 
1623  _SEH2_TRY
1624  {
1625  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
1626 
1627  /* If we had IRPs waiting for the lock, complete them */
1628  for (NextEntry = IntOplock->WaitListHead.Flink;
1629  NextEntry != &IntOplock->WaitListHead;
1630  NextEntry = NextEntry->Flink)
1631  {
1632  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
1633  Irp = WaitCtx->Irp;
1634 
1635  RemoveEntryList(&WaitCtx->WaitListEntry);
1636  /* Remove the cancel routine */
1637  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1639  IoReleaseCancelSpinLock(Irp->CancelIrql);
1640 
1641  /* And complete */
1642  Irp->IoStatus.Information = 0;
1643  WaitCtx->CompletionRoutine(WaitCtx->CompletionContext, WaitCtx->Irp);
1644 
1645  ExFreePoolWithTag(WaitCtx, TAG_OPLOCK);
1646  }
1647 
1648  /* If we had shared IRPs (LEVEL_2), complete them */
1649  for (NextEntry = IntOplock->SharedListHead.Flink;
1650  NextEntry != &IntOplock->SharedListHead;
1651  NextEntry = NextEntry->Flink)
1652  {
1653  Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1654 
1655  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1656 
1657  /* Remvoe the cancel routine */
1658  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1660  IoReleaseCancelSpinLock(Irp->CancelIrql);
1661 
1662  /* Dereference the file object */
1665 
1666  /* And complete */
1667  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1668  Irp->IoStatus.Status = STATUS_SUCCESS;
1670  }
1671 
1672  /* If we have an exclusive IRP, complete it */
1673  Irp = IntOplock->ExclusiveIrp;
1674  if (Irp != NULL)
1675  {
1676  /* Remvoe the cancel routine */
1677  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1679  IoReleaseCancelSpinLock(Irp->CancelIrql);
1680 
1681  /* And complete */
1682  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1683  Irp->IoStatus.Status = STATUS_SUCCESS;
1685  IntOplock->ExclusiveIrp = NULL;
1686 
1687  /* If still referenced, dereference */
1688  if (IntOplock->FileObject != NULL)
1689  {
1690  ObDereferenceObject(IntOplock->FileObject);
1691  }
1692  }
1693  }
1695  {
1696  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
1697  }
1698  _SEH2_END;
1699 
1700  ExFreePoolWithTag(IntOplock->IntLock, TAG_OPLOCK);
1701  ExFreePoolWithTag(IntOplock, TAG_OPLOCK);
1702 }
PFILE_OBJECT FileObject
Definition: oplock.c:37
PVOID CompletionContext
Definition: oplock.c:51
PFAST_MUTEX IntLock
Definition: oplock.c:43
_In_ PIRP Irp
Definition: csq.h:116
LIST_ENTRY SharedListHead
Definition: oplock.c:39
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
LIST_ENTRY WaitListHead
Definition: oplock.c:41
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define TAG_OPLOCK
Definition: oplock.c:30
IRP
Definition: iotypes.h:2463
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
PIRP ExclusiveIrp
Definition: oplock.c:35
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
void DPRINT(...)
Definition: polytest.cpp:61
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
LIST_ENTRY WaitListEntry
Definition: oplock.c:48
Definition: typedefs.h:117
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: oplock.c:50
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
_SEH2_FINALLY
Definition: create.c:4395
PIRP Irp
Definition: oplock.c:49
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define FILE_OPLOCK_BROKEN_TO_NONE
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by CdDeleteFcb(), Ext2FreeFcb(), FatCreateDcb(), FatCreateFcb(), FatDeleteFcb(), and reap_fcb().

◆ FsRtlWaitOnIrp()

VOID FsRtlWaitOnIrp ( IN PINTERNAL_OPLOCK  Oplock,
IN PIRP  Irp,
IN PVOID  CompletionContext,
IN POPLOCK_WAIT_COMPLETE_ROUTINE  CompletionRoutine,
IN POPLOCK_FS_PREPOST_IRP  PostIrpRoutine,
IN PKEVENT  WaitEvent 
)

Definition at line 150 of file oplock.c.

156 {
157  BOOLEAN Locked;
158  PWAIT_CONTEXT WaitCtx;
159 
160  DPRINT("FsRtlWaitOnIrp(%p, %p, %p, %p, %p, %p)\n", Oplock, Irp, CompletionContext, CompletionRoutine, PostIrpRoutine, WaitEvent);
161 
162  /* We must always be called with IntLock locked! */
163  Locked = TRUE;
164  /* Dirty check for above statement */
165  ASSERT(Oplock->IntLock->Owner == KeGetCurrentThread());
166 
167  /* Allocate a wait context for the IRP */
169  WaitCtx->Irp = Irp;
170  WaitCtx->SavedInformation = Irp->IoStatus.Information;
171  /* If caller provided everything required, us it */
172  if (CompletionRoutine != NULL)
173  {
176  }
177  /* Otherwise, put ourselves */
178  else
179  {
181  WaitCtx->CompletionContext = WaitEvent;
183  }
184 
185  /* If we got a prepost routine, call it now! */
186  if (PostIrpRoutine != NULL)
187  {
189  }
190 
191  Irp->IoStatus.Status = STATUS_SUCCESS;
192 
193  /* Queue the IRP - it's OK, we're locked */
194  InsertHeadList(&Oplock->WaitListHead, &WaitCtx->WaitListEntry);
195 
196  /* Set the oplock as information of the IRP (for the cancel routine)
197  * And lock the cancel routine lock for setting it
198  */
199  IoAcquireCancelSpinLock(&Irp->CancelIrql);
200  Irp->IoStatus.Information = (ULONG_PTR)Oplock;
201 
202  /* If there's already a cancel routine
203  * Cancel the IRP
204  */
205  if (Irp->Cancel)
206  {
207  ExReleaseFastMutexUnsafe(Oplock->IntLock);
208  Locked = FALSE;
209 
210  if (CompletionRoutine != NULL)
211  {
213  }
215  }
216  /* Otherwise, put ourselves as the cancel routine and start waiting */
217  else
218  {
220  IoReleaseCancelSpinLock(Irp->CancelIrql);
221  if (CompletionRoutine != NULL)
222  {
224  }
225  else
226  {
227  ExReleaseFastMutexUnsafe(Oplock->IntLock);
228  Locked = FALSE;
230  }
231  }
232 
233  /* If we didn't unlock yet, do it now */
234  if (Locked)
235  {
236  ExReleaseFastMutexUnsafe(Oplock->IntLock);
237  }
238 }
PVOID CompletionContext
Definition: oplock.c:51
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define TAG_OPLOCK
Definition: oplock.c:30
IoSetCancelRoutine(Irp, CancelRoutine)
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
ULONG_PTR SavedInformation
Definition: oplock.c:53
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:260
VOID NTAPI FsRtlCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:116
_Unreferenced_parameter_ PVOID * CompletionContext
Definition: cdprocs.h:1130
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
LIST_ENTRY WaitListEntry
Definition: oplock.c:48
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: oplock.c:50
VOID NTAPI FsRtlCompletionRoutinePriv(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:71
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
PIRP Irp
Definition: oplock.c:49
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
#define ULONG_PTR
Definition: config.h:101
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define KeGetCurrentThread
Definition: hal.h:44
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:673

Referenced by FsRtlOplockBreakNotify(), FsRtlOplockBreakToII(), and FsRtlOplockBreakToNone().