ReactOS  0.4.15-dev-3745-g356babc
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 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) \
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:1035
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PIRP Irp
Definition: csq.h:116
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
_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_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PIRP Irp
Definition: csq.h:116
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
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:901
_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.

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 356 of file oplock.c.

360 {
361  PLIST_ENTRY NextEntry;
362  PWAIT_CONTEXT WaitCtx;
363  BOOLEAN Deref;
364  BOOLEAN Locked;
365 
366  DPRINT("FsRtlAcknowledgeOplockBreak(%p, %p, %p, %u)\n", Oplock, Stack, Irp, Unknown);
367 
368  /* No oplock, nothing to acknowledge */
369  if (Oplock == NULL)
370  {
371  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
374  }
375 
376  /* Acquire oplock internal lock */
377  ExAcquireFastMutexUnsafe(Oplock->IntLock);
378  Locked = TRUE;
379  /* Does it match the file? */
380  if (Oplock->FileObject != Stack->FileObject)
381  {
382  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
384  ExReleaseFastMutexUnsafe(Oplock->IntLock);
386  }
387 
388  /* Assume we'll have to deref our extra ref (level I) */
389  Deref = TRUE;
390 
391  /* If we got broken to level 2 and asked for a shared lock
392  * switch the oplock to shared
393  */
394  if (SwitchToLevel2 && BooleanFlagOn(Oplock->Flags, BROKEN_TO_LEVEL_2))
395  {
396  /* The IRP cannot be synchronous, we'll move it to the LEVEL_2 IRPs */
398 
399  /* Mark the IRP pending, and queue it for the shared IRPs */
401  Irp->IoStatus.Status = STATUS_SUCCESS;
402  InsertTailList(&Oplock->SharedListHead, &Irp->Tail.Overlay.ListEntry);
403 
404  /* Don't deref, we're not done yet */
405  Deref = FALSE;
406  /* And mark we've got a shared lock */
407  Oplock->Flags = LEVEL_2_OPLOCK;
408  /* To find the lock back on cancel */
409  Irp->IoStatus.Information = (ULONG_PTR)Oplock;
410 
411  /* Acquire the spinlock to set the cancel routine */
412  IoAcquireCancelSpinLock(&Irp->CancelIrql);
413  /* If IRP got canceled, call it immediately */
414  if (Irp->Cancel)
415  {
416  ExReleaseFastMutexUnsafe(Oplock->IntLock);
417  Locked = FALSE;
419  }
420  /* Otherwise, just set our cancel routine */
421  else
422  {
424  IoReleaseCancelSpinLock(Irp->CancelIrql);
425  }
426  }
427  /* If oplock got broken, remove it */
428  else if (BooleanFlagOn(Oplock->Flags, (BROKEN_TO_NONE | BROKEN_TO_LEVEL_2)))
429  {
430  Irp->IoStatus.Status = STATUS_SUCCESS;
432  Oplock->Flags = NO_OPLOCK;
433  }
434  /* Same, but precise we got broken from none to shared */
435  else if (BooleanFlagOn(Oplock->Flags, BROKEN_TO_NONE_FROM_LEVEL_2))
436  {
437  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
438  Irp->IoStatus.Status = STATUS_SUCCESS;
440  Oplock->Flags = NO_OPLOCK;
441  }
442 
443  /* Now, complete any IRP waiting */
444  for (NextEntry = Oplock->WaitListHead.Flink;
445  NextEntry != &Oplock->WaitListHead;
446  NextEntry = NextEntry->Flink)
447  {
448  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
450  }
451 
452  /* If we dropped oplock, remove our extra ref */
453  if (Deref)
454  {
455  ObDereferenceObject(Oplock->FileObject);
456  }
457  /* And unset FO: no oplock left or shared */
458  Oplock->FileObject = NULL;
459 
460  /* Don't leak the mutex! */
461  if (Locked)
462  {
463  ExReleaseFastMutexUnsafe(Oplock->IntLock);
464  }
465 
466  return STATUS_SUCCESS;
467 }
#define TRUE
Definition: types.h:120
#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:463
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
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
unsigned char BOOLEAN
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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:121
#define ASSERT(a)
Definition: mode.c:44
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ObDereferenceObject
Definition: obfuncs.h:203
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:119
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
#define NULL
Definition: types.h:112
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71
IoMarkIrpPending(Irp)
VOID NTAPI FsRtlCancelOplockIIIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:311

Referenced by FsRtlOplockFsctrl().

◆ FsRtlAllocateOplock()

PINTERNAL_OPLOCK FsRtlAllocateOplock ( VOID  )

Definition at line 542 of file oplock.c.

543 {
544  PINTERNAL_OPLOCK Oplock = NULL;
545 
546  PAGED_CODE();
547 
548  DPRINT("FsRtlAllocateOplock()\n");
549 
550  _SEH2_TRY
551  {
552  /* Allocate and initialize the oplock */
554  RtlZeroMemory(Oplock, sizeof(INTERNAL_OPLOCK));
555  /* We allocate the fast mutex separately to have it non paged (while the rest of the oplock can be paged) */
558  /* Initialize the IRP list for level 2 oplock */
560  /* And for the wait IRPs */
562  Oplock->Flags = NO_OPLOCK;
563  }
565  {
566  /* In case of abnormal termination, it means either OPLOCK or FAST_MUTEX allocation failed */
568  {
569  /* That FAST_MUTEX, free OPLOCK */
570  if (Oplock != NULL)
571  {
572  ExFreePoolWithTag(Oplock, TAG_OPLOCK);
573  Oplock = NULL;
574  }
575  }
576  }
577  _SEH2_END;
578 
579  return Oplock;
580 }
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY SharedListHead
Definition: oplock.c:37
#define POOL_COLD_ALLOCATION
LIST_ENTRY WaitListHead
Definition: oplock.c:39
#define TAG_OPLOCK
Definition: tag.h:49
_SEH2_TRY
Definition: create.c:4226
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
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:4400
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define DPRINT
Definition: sndvol32.h:71
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define PAGED_CODE()
ULONG Flags
Definition: oplock.c:40

Referenced by FsRtlRequestExclusiveOplock(), and FsRtlRequestOplockII().

◆ FsRtlCancelExclusiveIrp()

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

Definition at line 584 of file oplock.c.

586 {
587  PINTERNAL_OPLOCK IntOplock;
588  PLIST_ENTRY NextEntry;
589  PWAIT_CONTEXT WaitCtx;
590 
591  DPRINT("FsRtlCancelExclusiveIrp(%p, %p)\n", DeviceObject, Irp);
592 
593  /* Get the associated oplock */
594  IntOplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
595 
596  /* Remove the cancel routine (us!) and release the cancel spinlock */
598  IoReleaseCancelSpinLock(Irp->CancelIrql);
599 
600  /* Acquire our internal FAST_MUTEX */
601  ExAcquireFastMutex(IntOplock->IntLock);
602  /* If we had an exclusive IRP */
603  if (IntOplock->ExclusiveIrp != NULL && IntOplock->ExclusiveIrp->Cancel)
604  {
605  /* Cancel it, and remove it from the oplock */
608  IntOplock->ExclusiveIrp = NULL;
609 
610  /* Dereference the fileobject and remove the oplock */
611  ObDereferenceObject(IntOplock->FileObject);
612  IntOplock->FileObject = NULL;
613  IntOplock->Flags = NO_OPLOCK;
614 
615  /* And complete any waiting IRP */
616  for (NextEntry = IntOplock->WaitListHead.Flink;
617  NextEntry != &IntOplock->WaitListHead;
618  NextEntry = NextEntry->Flink)
619  {
620  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
622  }
623  }
624 
625  /* Done! */
626  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
627 }
PFILE_OBJECT FileObject
Definition: oplock.c:35
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY WaitListHead
Definition: oplock.c:39
IO_STATUS_BLOCK IoStatus
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
PIRP ExclusiveIrp
Definition: oplock.c:33
_In_ PIRP Irp
Definition: csq.h:116
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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:121
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
#define ObDereferenceObject
Definition: obfuncs.h:203
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
Definition: typedefs.h:119
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define NULL
Definition: types.h:112
#define DPRINT
Definition: sndvol32.h:71
ULONG Flags
Definition: oplock.c:40

Referenced by FsRtlRequestExclusiveOplock().

◆ FsRtlCancelOplockIIIrp()

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

Definition at line 311 of file oplock.c.

313 {
314  PINTERNAL_OPLOCK Oplock;
315  PLIST_ENTRY NextEntry;
316  PIRP ListIrp;
318 
319  DPRINT("FsRtlCancelOplockIIIrp(%p, %p)\n", DeviceObject, Irp);
320 
321  /* Get the associated oplock */
322  Oplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
323 
324  /* Remove the cancel routine (it's OK, we're the cancel routine! )*/
326  IoReleaseCancelSpinLock(Irp->CancelIrql);
327 
328  /* Nothing removed yet */
329  Removed = FALSE;
330  ExAcquireFastMutex(Oplock->IntLock);
331  /* Browse all the IRPs associated to the shared lock */
332  for (NextEntry = Oplock->SharedListHead.Flink;
333  NextEntry != &Oplock->SharedListHead;
334  NextEntry = NextEntry->Flink)
335  {
336  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
337 
338  /* If canceled, remove it */
339  if (ListIrp->Cancel)
340  {
341  FsRtlRemoveAndCompleteIrp(ListIrp);
342  Removed = TRUE;
343  }
344  }
345 
346  /* If no IRP left, the oplock is gone */
347  if (Removed && IsListEmpty(&Oplock->SharedListHead))
348  {
349  Oplock->Flags = NO_OPLOCK;
350  }
351  /* Don't forget to release the mutex */
352  ExReleaseFastMutex(Oplock->IntLock);
353 }
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY SharedListHead
Definition: oplock.c:37
#define TRUE
Definition: types.h:120
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
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
unsigned char BOOLEAN
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:121
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:283
Definition: typedefs.h:119
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define NULL
Definition: types.h:112
Definition: fbtusb.h:86
#define DPRINT
Definition: sndvol32.h:71
ULONG Flags
Definition: oplock.c:40

Referenced by FsRtlAcknowledgeOplockBreak(), and FsRtlRequestOplockII().

◆ FsRtlCancelWaitIrp()

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

Definition at line 114 of file oplock.c.

116 {
117  PINTERNAL_OPLOCK Oplock;
118  PLIST_ENTRY NextEntry;
119  PWAIT_CONTEXT WaitCtx;
120 
121  DPRINT("FsRtlCancelWaitIrp(%p, %p)\n", DeviceObject, Irp);
122 
123  /* Get the associated oplock */
124  Oplock = (PINTERNAL_OPLOCK)Irp->IoStatus.Information;
125 
126  /* Remove the cancel routine (we're being called!) */
128  /* And release the cancel spin lock (always locked when cancel routine is called) */
129  IoReleaseCancelSpinLock(Irp->CancelIrql);
130 
131  /* Now, remove and complete any associated waiter */
132  ExAcquireFastMutex(Oplock->IntLock);
133  for (NextEntry = Oplock->WaitListHead.Flink;
134  NextEntry != &Oplock->WaitListHead;
135  NextEntry = NextEntry->Flink)
136  {
137  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
138 
139  if (WaitCtx->Irp->Cancel)
140  {
142  }
143  }
144  ExReleaseFastMutex(Oplock->IntLock);
145 }
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY WaitListHead
Definition: oplock.c:39
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
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:121
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
Definition: typedefs.h:119
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
#define NULL
Definition: types.h:112
PIRP Irp
Definition: oplock.c:47
#define DPRINT
Definition: sndvol32.h:71

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 1170 of file oplock.c.

1175 {
1176  PINTERNAL_OPLOCK IntOplock;
1181 
1182 #define BreakToIIIfRequired \
1183  if (IntOplock->Flags != LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
1184  return FsRtlOplockBreakToII(IntOplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine)
1185 
1186 #define BreakToNoneIfRequired \
1187  if (IntOplock->Flags == LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
1188  return FsRtlOplockBreakToNone(IntOplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine)
1189 
1190  DPRINT("FsRtlCheckOplock(%p, %p, %p, %p, %p)\n", Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine);
1191 
1192  IntOplock = *Oplock;
1193 
1194  /* No oplock, easy! */
1195  if (IntOplock == NULL)
1196  {
1197  return STATUS_SUCCESS;
1198  }
1199 
1200  /* No sense on paging */
1201  if (Irp->Flags & IRP_PAGING_IO)
1202  {
1203  return STATUS_SUCCESS;
1204  }
1205 
1206  /* No oplock, easy (bis!) */
1207  if (IntOplock->Flags == NO_OPLOCK)
1208  {
1209  return STATUS_SUCCESS;
1210  }
1211 
1213 
1214  /* If cleanup, cleanup the associated oplock & return */
1215  if (Stack->MajorFunction == IRP_MJ_CLEANUP)
1216  {
1217  FsRtlOplockCleanup(IntOplock, Stack);
1218  return STATUS_SUCCESS;
1219  }
1220  else if (Stack->MajorFunction == IRP_MJ_LOCK_CONTROL)
1221  {
1222  /* OK for filter */
1223  if (BooleanFlagOn(IntOplock->Flags, FILTER_OPLOCK))
1224  {
1225  return STATUS_SUCCESS;
1226  }
1227 
1228  /* Lock operation, we will have to break to no lock if shared or not us */
1230 
1231  return STATUS_SUCCESS;
1232  }
1233  else if (Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
1234  {
1235  /* FSCTL should be safe, unless user wants a write FSCTL */
1236  if (Stack->Parameters.FileSystemControl.FsControlCode != FSCTL_SET_ZERO_DATA)
1237  {
1238  return STATUS_SUCCESS;
1239  }
1240 
1241  /* We will have to break for write if shared or not us! */
1243 
1244  return STATUS_SUCCESS;
1245  }
1246  else if (Stack->MajorFunction == IRP_MJ_WRITE)
1247  {
1248  /* Write operation, we will have to break if shared or not us */
1250 
1251  return STATUS_SUCCESS;
1252  }
1253  else if (Stack->MajorFunction == IRP_MJ_READ)
1254  {
1255  /* If that's filter oplock, it's alright */
1256  if (BooleanFlagOn(IntOplock->Flags, FILTER_OPLOCK))
1257  {
1258  return STATUS_SUCCESS;
1259  }
1260 
1261  /* Otherwise, we need to break to shared oplock */
1263 
1264  return STATUS_SUCCESS;
1265  }
1266  else if (Stack->MajorFunction == IRP_MJ_CREATE)
1267  {
1268  DesiredAccess = Stack->Parameters.Create.SecurityContext->DesiredAccess;
1269 
1270  /* If that's just for reading, the oplock is fine */
1273  {
1274  return STATUS_SUCCESS;
1275  }
1276 
1277  /* Otherwise, check the disposition */
1278  CreateDisposition = (Stack->Parameters.Create.Options >> 24) & 0x000000FF;
1281  BooleanFlagOn(Stack->Parameters.Create.Options, FILE_RESERVE_OPFILTER))
1282  {
1283  /* Not us, we have to break the oplock! */
1285 
1286  return STATUS_SUCCESS;
1287  }
1288 
1289  /* It's fine, we can have the oplock shared */
1291 
1292  return STATUS_SUCCESS;
1293  }
1294  else if (Stack->MajorFunction == IRP_MJ_FLUSH_BUFFERS)
1295  {
1296  /* We need to share the lock, if not done yet! */
1298 
1299  return STATUS_SUCCESS;
1300  }
1301  else if (Stack->MajorFunction == IRP_MJ_SET_INFORMATION)
1302  {
1303  /* Only deal with really specific classes */
1304  FileInfo = Stack->Parameters.SetFile.FileInformationClass;
1307  {
1308  /* No need to break */
1309  if (!BooleanFlagOn(IntOplock->Flags, (FILTER_OPLOCK | BATCH_OPLOCK)))
1310  {
1311  return STATUS_SUCCESS;
1312  }
1313  /* Otherwise break to none */
1314  else
1315  {
1317 
1318  return STATUS_SUCCESS;
1319  }
1320  }
1321  else if (FileInfo == FileAllocationInformation)
1322  {
1324 
1325  return STATUS_SUCCESS;
1326  }
1327  else if (FileInfo == FileEndOfFileInformation)
1328  {
1329  /* Advance only, nothing to do */
1330  if (Stack->Parameters.SetFile.AdvanceOnly)
1331  {
1332  return STATUS_SUCCESS;
1333  }
1334 
1335  /* Otherwise, attempt to break to none */
1337 
1338  return STATUS_SUCCESS;
1339  }
1340  }
1341 
1342 #undef BreakToIIIfRequired
1343 #undef BreakToNoneIfRequired
1344 
1345  return STATUS_SUCCESS;
1346 }
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BATCH_OPLOCK
Definition: oplock.c:17
#define IRP_MJ_FLUSH_BUFFERS
#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:136
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
_In_ PIRP Irp
Definition: csq.h:116
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_WRITE_DATA
Definition: nt_native.h:631
VOID FsRtlOplockCleanup(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack)
Definition: oplock.c:816
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG _Out_opt_ PULONG CreateDisposition
Definition: wdfregistry.h:112
#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:2793
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
#define FILE_READ_EA
Definition: nt_native.h:638
#define NULL
Definition: types.h:112
#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
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
unsigned int ULONG
Definition: retypes.h:1
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
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:40

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 69 of file oplock.c.

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

Referenced by FsRtlWaitOnIrp().

◆ FsRtlCurrentBatchOplock()

BOOLEAN NTAPI FsRtlCurrentBatchOplock ( IN POPLOCK  Oplock)

Definition at line 1364 of file oplock.c.

1365 {
1366  PINTERNAL_OPLOCK IntOplock;
1367 
1368  PAGED_CODE();
1369 
1370  DPRINT("FsRtlCurrentBatchOplock(%p)\n", Oplock);
1371 
1372  IntOplock = *Oplock;
1373 
1374  /* Only return true if batch or filter oplock */
1375  if (IntOplock != NULL &&
1376  BooleanFlagOn(IntOplock->Flags, (FILTER_OPLOCK | BATCH_OPLOCK)))
1377  {
1378  return TRUE;
1379  }
1380 
1381  return FALSE;
1382 }
#define BATCH_OPLOCK
Definition: oplock.c:17
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FILTER_OPLOCK
Definition: oplock.c:18
#define FALSE
Definition: types.h:117
#define NULL
Definition: types.h:112
#define DPRINT
Definition: sndvol32.h:71
#define PAGED_CODE()
ULONG Flags
Definition: oplock.c:40

Referenced by Ext2CreateFile(), and FatSetRenameInfo().

◆ FsRtlInitializeOplock()

VOID NTAPI FsRtlInitializeOplock ( IN OUT POPLOCK  Oplock)

Definition at line 1400 of file oplock.c.

1401 {
1402  PAGED_CODE();
1403 
1404  /* Nothing to do */
1405  DPRINT("FsRtlInitializeOplock(%p)\n", Oplock);
1406 }
#define DPRINT
Definition: sndvol32.h:71
#define PAGED_CODE()

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

◆ FsRtlNotifyCompletion()

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

Definition at line 56 of file oplock.c.

58 {
59  PAGED_CODE();
60 
61  DPRINT("FsRtlNotifyCompletion(%p, %p)\n", Context, Irp);
62 
63  /* Just complete the IRP */
65 }
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
#define IoCompleteRequest
Definition: irp.c:1240
#define DPRINT
Definition: sndvol32.h:71
#define PAGED_CODE()

Referenced by FsRtlOplockBreakNotify().

◆ FsRtlOpBatchBreakClosePending()

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

Definition at line 470 of file oplock.c.

473 {
475  PLIST_ENTRY NextEntry;
476  PWAIT_CONTEXT WaitCtx;
477 
478  PAGED_CODE();
479 
480  DPRINT("FsRtlOpBatchBreakClosePending(%p, %p, %p)\n", Oplock, Stack, Irp);
481 
482  /* No oplock, that's not legit! */
483  if (Oplock == NULL)
484  {
485  Irp->IoStatus.Status = STATUS_INVALID_OPLOCK_PROTOCOL;
488  }
489 
491  ExAcquireFastMutexUnsafe(Oplock->IntLock);
492 
493  /* First of all, check if all conditions are met:
494  * Correct FO + broken oplock
495  */
496  if (Oplock->FileObject == Stack->FileObject && (BooleanFlagOn(Oplock->Flags, (BROKEN_TO_LEVEL_2 | BROKEN_TO_NONE | BROKEN_TO_NONE_FROM_LEVEL_2))))
497  {
498  /* If we have a pending or level 1 oplock... */
499  if (BooleanFlagOn(Oplock->Flags, (PENDING_LOCK | LEVEL_1_OPLOCK)))
500  {
501  /* Remove our extra ref from the FO */
502  if (Oplock->Flags & LEVEL_1_OPLOCK)
503  {
504  ObDereferenceObject(Oplock->FileObject);
505  }
506 
507  /* And remove the oplock */
508  Oplock->Flags = NO_OPLOCK;
509  Oplock->FileObject = NULL;
510 
511  /* Complete any waiting IRP */
512  for (NextEntry = Oplock->WaitListHead.Flink;
513  NextEntry != &Oplock->WaitListHead;
514  NextEntry = NextEntry->Flink)
515  {
516  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
518  }
519  }
520  /* Otherwise, mark the oplock as close pending */
521  else
522  {
523  ClearFlag(Oplock->Flags, BROKEN_ANY);
524  SetFlag(Oplock->Flags, BROKEN_TO_CLOSE_PENDING);
525  }
526  }
527  /* Oplock is in invalid state */
528  else
529  {
531  }
532 
533  /* And complete */
534  Irp->IoStatus.Status = Status;
536  ExReleaseFastMutexUnsafe(Oplock->IntLock);
537 
538  return Status;
539 }
#define PENDING_LOCK
Definition: oplock.c:22
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_OPLOCK_PROTOCOL
Definition: ntstatus.h:463
#define BROKEN_TO_NONE
Definition: oplock.c:25
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
#define BROKEN_ANY
Definition: oplock.c:28
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define BROKEN_TO_CLOSE_PENDING
Definition: oplock.c:27
#define ObDereferenceObject
Definition: obfuncs.h:203
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:119
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
#define NO_OPLOCK
Definition: oplock.c:15
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define NULL
Definition: types.h:112
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
#define PAGED_CODE()

Referenced by FsRtlOplockFsctrl().

◆ FsRtlOplockBreakNotify()

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

Definition at line 239 of file oplock.c.

242 {
243  PAGED_CODE();
244 
245  DPRINT("FsRtlOplockBreakNotify(%p, %p, %p)\n", Oplock, Stack, Irp);
246 
247  /* No oplock, no break to notify */
248  if (Oplock == NULL)
249  {
250  Irp->IoStatus.Status = STATUS_SUCCESS;
252  return STATUS_SUCCESS;
253  }
254 
255  /* Notify by completing the IRP, unless we have broken to shared */
256  ExAcquireFastMutexUnsafe(Oplock->IntLock);
257  if (!BooleanFlagOn(Oplock->Flags, BROKEN_TO_LEVEL_2))
258  {
259  Irp->IoStatus.Status = STATUS_SUCCESS;
261  ExReleaseFastMutexUnsafe(Oplock->IntLock);
262  return STATUS_SUCCESS;
263  }
264 
265  /* If it's pending, just complete the IRP and get rid of the oplock */
266  if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
267  {
268  Oplock->FileObject = NULL;
269  Oplock->Flags = NO_OPLOCK;
270  Irp->IoStatus.Status = STATUS_SUCCESS;
272  ExReleaseFastMutexUnsafe(Oplock->IntLock);
273  return STATUS_SUCCESS;
274  }
275 
276  /* Otherwise, wait on the IRP */
277  Irp->IoStatus.Status = STATUS_SUCCESS;
279  return STATUS_SUCCESS;
280 }
#define PENDING_LOCK
Definition: oplock.c:22
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
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:148
#define IoCompleteRequest
Definition: irp.c:1240
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
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI FsRtlNotifyCompletion(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:56
#define PAGED_CODE()

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 1035 of file oplock.c.

1041 {
1042  PLIST_ENTRY NextEntry;
1043  PWAIT_CONTEXT WaitCtx;
1044  KEVENT WaitEvent;
1045 
1046  DPRINT("FsRtlOplockBreakToII(%p, %p, %p, %p, %p, %p)\n", Oplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine);
1047 
1048  ExAcquireFastMutexUnsafe(Oplock->IntLock);
1049 
1050  /* If our lock, or if not exclusively locked, nothing to break! */
1051  if (!BooleanFlagOn(Oplock->Flags, EXCLUSIVE_LOCK) || Oplock->FileObject == Stack->FileObject)
1052  {
1053  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1054  return STATUS_SUCCESS;
1055  }
1056 
1057  /* If already broken or not set yet */
1058  if (BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK)))
1059  {
1060  /* Drop oplock if pending */
1061  if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
1062  {
1063  Oplock->Flags = NO_OPLOCK;
1064  Oplock->FileObject = NULL;
1065 
1066  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1067  return STATUS_SUCCESS;
1068  }
1069 
1070  }
1071  /* To break! */
1072  else
1073  {
1074  /* Drop the cancel routine of the exclusive IRP */
1075  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
1076  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
1077  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
1078 
1079  /* If it was canceled in between, break to no oplock */
1080  if (Oplock->ExclusiveIrp->Cancel)
1081  {
1082  /* Complete the IRP with cancellation */
1083  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1084  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_CANCELLED;
1085  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
1086 
1087  /* And mark we have no longer lock */
1088  Oplock->Flags = NO_OPLOCK;
1089  Oplock->ExclusiveIrp = NULL;
1090  ObDereferenceObject(Oplock->FileObject);
1091  Oplock->FileObject = NULL;
1092 
1093  /* Finally, complete any waiter */
1094  for (NextEntry = Oplock->WaitListHead.Flink;
1095  NextEntry != &Oplock->WaitListHead;
1096  NextEntry = NextEntry->Flink)
1097  {
1098  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
1100  }
1101 
1102  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1103 
1104  return STATUS_SUCCESS;
1105  }
1106 
1107  /* It wasn't canceled, so break to shared unless we were alone, in that case we break to no lock! */
1108  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
1109  if (BooleanFlagOn(Oplock->Flags, (BATCH_OPLOCK | LEVEL_1_OPLOCK)))
1110  {
1111  SetFlag(Oplock->Flags, BROKEN_TO_LEVEL_2);
1112  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_LEVEL_2;
1113  }
1114  else
1115  {
1116  SetFlag(Oplock->Flags, BROKEN_TO_NONE);
1117  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1118  }
1119  /* And complete */
1120  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
1121  Oplock->ExclusiveIrp = NULL;
1122  }
1123 
1124  /* Wait if required */
1125  if (Stack->MajorFunction != IRP_MJ_CREATE || !BooleanFlagOn(Stack->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED))
1126  {
1127  FsRtlWaitOnIrp(Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine, &WaitEvent);
1128 
1129  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1130 
1131  return STATUS_SUCCESS;
1132  }
1133  else
1134  {
1135  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1137  }
1138 }
#define PENDING_LOCK
Definition: oplock.c:22
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BATCH_OPLOCK
Definition: oplock.c:17
#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
#define BROKEN_TO_NONE
Definition: oplock.c:25
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
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:148
#define BROKEN_ANY
Definition: oplock.c:28
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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:121
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ObDereferenceObject
Definition: obfuncs.h:203
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:119
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
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
#define NULL
Definition: types.h:112
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71
#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 901 of file oplock.c.

907 {
908  PLIST_ENTRY NextEntry;
909  PWAIT_CONTEXT WaitCtx;
910  PIRP ListIrp;
911  KEVENT WaitEvent;
912 
913  DPRINT("FsRtlOplockBreakToNone(%p, %p, %p, %p, %p, %p)\n", Oplock, Stack, Irp, Context, CompletionRoutine, PostIrpRoutine);
914 
915  ExAcquireFastMutexUnsafe(Oplock->IntLock);
916 
917  /* No oplock to break! */
918  if (Oplock->Flags == NO_OPLOCK)
919  {
920  ExReleaseFastMutexUnsafe(Oplock->IntLock);
921  return STATUS_SUCCESS;
922  }
923 
924  /* Not broken yet, but set... Let's do it!
925  * Also, we won't break a shared oplock
926  */
927  if (!BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK | LEVEL_2_OPLOCK)))
928  {
929  /* Remove our cancel routine, no longer needed */
930  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
931  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
932  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
933 
934  /* If the IRP got canceled, we need to cleanup a bit */
935  if (Oplock->ExclusiveIrp->Cancel)
936  {
937  /* Return cancelation */
938  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
939  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_CANCELLED;
940  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
941 
942  /* No oplock left */
943  Oplock->Flags = NO_OPLOCK;
944  Oplock->ExclusiveIrp = NULL;
945 
946  /* No need for the FO anymore */
947  ObDereferenceObject(Oplock->FileObject);
948  Oplock->FileObject = NULL;
949 
950  /* And complete any waiting IRP */
951  for (NextEntry = Oplock->WaitListHead.Flink;
952  NextEntry != &Oplock->WaitListHead;
953  NextEntry = NextEntry->Flink)
954  {
955  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
957  }
958 
959  /* Done! */
960  ExReleaseFastMutexUnsafe(Oplock->IntLock);
961 
962  return STATUS_SUCCESS;
963  }
964 
965  /* Easier break, just complete :-) */
966  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
967  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
968  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
969 
970  /* And remove our exclusive IRP */
971  Oplock->ExclusiveIrp = NULL;
972  SetFlag(Oplock->Flags, BROKEN_TO_NONE);
973  }
974  /* Shared lock */
975  else if (Oplock->Flags == LEVEL_2_OPLOCK)
976  {
977  /* Complete any IRP in the shared lock */
978  for (NextEntry = Oplock->SharedListHead.Flink;
979  NextEntry != &Oplock->SharedListHead;
980  NextEntry = NextEntry->Flink)
981  {
982  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
983  FsRtlRemoveAndCompleteIrp(ListIrp);
984  }
985 
986  /* No lock left */
987  Oplock->Flags = NO_OPLOCK;
988 
989  /* Done */
990  ExReleaseFastMutexUnsafe(Oplock->IntLock);
991  return STATUS_SUCCESS;
992  }
993  /* If it was broken to level 2, break it to none from level 2 */
994  else if (Oplock->Flags & BROKEN_TO_LEVEL_2)
995  {
996  ClearFlag(Oplock->Flags, BROKEN_TO_LEVEL_2);
997  SetFlag(Oplock->Flags, BROKEN_TO_NONE_FROM_LEVEL_2);
998  }
999  /* If it was pending, just drop the lock */
1000  else if (BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
1001  {
1002  Oplock->Flags = NO_OPLOCK;
1003  Oplock->FileObject = NULL;
1004 
1005  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1006  return STATUS_SUCCESS;
1007  }
1008 
1009  /* If that's ours, job done */
1010  if (Oplock->FileObject == Stack->FileObject)
1011  {
1012  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1013  return STATUS_SUCCESS;
1014  }
1015 
1016  /* Otherwise, wait on the IRP */
1017  if (Stack->MajorFunction != IRP_MJ_CREATE || !BooleanFlagOn(Stack->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED))
1018  {
1019  FsRtlWaitOnIrp(Oplock, Irp, Context, CompletionRoutine, PostIrpRoutine, &WaitEvent);
1020 
1021  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1022 
1023  return STATUS_SUCCESS;
1024  }
1025  /* Done */
1026  else
1027  {
1028  ExReleaseFastMutexUnsafe(Oplock->IntLock);
1030  }
1031 }
#define PENDING_LOCK
Definition: oplock.c:22
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define BROKEN_TO_NONE
Definition: oplock.c:25
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ PIRP Irp
Definition: csq.h:116
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:148
#define BROKEN_ANY
Definition: oplock.c:28
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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:121
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ObDereferenceObject
Definition: obfuncs.h:203
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:283
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
Definition: typedefs.h:119
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
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
#define NULL
Definition: types.h:112
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71
#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 816 of file oplock.c.

818 {
819  PIO_STACK_LOCATION ListStack;
820  PLIST_ENTRY NextEntry;
821  PIRP ListIrp;
822  PWAIT_CONTEXT WaitCtx;
823 
824  DPRINT("FsRtlOplockCleanup(%p, %p)\n", Oplock, Stack);
825 
826  ExAcquireFastMutexUnsafe(Oplock->IntLock);
827  /* oplock cleaning only makes sense if there's an oplock */
828  if (Oplock->Flags != NO_OPLOCK)
829  {
830  /* Shared lock */
831  if (Oplock->Flags == LEVEL_2_OPLOCK)
832  {
833  /* Complete any associated IRP */
834  for (NextEntry = Oplock->SharedListHead.Flink;
835  NextEntry != &Oplock->SharedListHead;
836  NextEntry = NextEntry->Flink)
837  {
838  ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
839  ListStack = IoGetCurrentIrpStackLocation(ListIrp);
840 
841  if (Stack->FileObject == ListStack->FileObject)
842  {
843  FsRtlRemoveAndCompleteIrp(ListIrp);
844  }
845  }
846 
847  /* If, in the end, no IRP is left, then the lock is gone */
848  if (IsListEmpty(&Oplock->SharedListHead))
849  {
850  Oplock->Flags = NO_OPLOCK;
851  }
852  }
853  else
854  {
855  /* If we have matching file */
856  if (Oplock->FileObject == Stack->FileObject)
857  {
858  /* Oplock wasn't broken (still exclusive), easy case */
859  if (!BooleanFlagOn(Oplock->Flags, (BROKEN_ANY | PENDING_LOCK)))
860  {
861  /* Remove the cancel routine we set previously */
862  IoAcquireCancelSpinLock(&Oplock->ExclusiveIrp->CancelIrql);
863  IoSetCancelRoutine(Oplock->ExclusiveIrp, NULL);
864  IoReleaseCancelSpinLock(Oplock->ExclusiveIrp->CancelIrql);
865 
866  /* And return the fact we broke the oplock to no oplock */
867  Oplock->ExclusiveIrp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
868  Oplock->ExclusiveIrp->IoStatus.Status = STATUS_SUCCESS;
869 
870  /* And complete! */
871  IoCompleteRequest(Oplock->ExclusiveIrp, IO_DISK_INCREMENT);
872  Oplock->ExclusiveIrp = NULL;
873  }
874 
875  /* If no pending, we can safely dereference the file object */
876  if (!BooleanFlagOn(Oplock->Flags, PENDING_LOCK))
877  {
878  ObDereferenceObject(Oplock->FileObject);
879  }
880 
881  /* Now, remove the oplock */
882  Oplock->FileObject = NULL;
883  Oplock->Flags = NO_OPLOCK;
884 
885  /* And complete any waiting IRP */
886  for (NextEntry = Oplock->WaitListHead.Flink;
887  NextEntry != &Oplock->WaitListHead;
888  NextEntry = NextEntry->Flink)
889  {
890  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
892  }
893  }
894  }
895  }
896  ExReleaseFastMutexUnsafe(Oplock->IntLock);
897 }
#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
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
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
#define BROKEN_ANY
Definition: oplock.c:28
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
#define IoCompleteRequest
Definition: irp.c:1240
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:121
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ObDereferenceObject
Definition: obfuncs.h:203
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:283
Definition: typedefs.h:119
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:2793
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71

Referenced by FsRtlCheckOplock().

◆ FsRtlOplockFsctrl()

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

Definition at line 1430 of file oplock.c.

1433 {
1435  PINTERNAL_OPLOCK IntOplock;
1436 
1437  PAGED_CODE();
1438 
1439  DPRINT("FsRtlOplockFsctrl(%p, %p, %lu)\n", Oplock, Irp, OpenCount);
1440 
1441  IntOplock = *Oplock;
1443  /* Make sure it's not called on create */
1444  if (Stack->MajorFunction != IRP_MJ_CREATE)
1445  {
1446  switch (Stack->Parameters.FileSystemControl.FsControlCode)
1447  {
1449  return FsRtlOplockBreakNotify(IntOplock, Stack, Irp);
1450 
1452  return FsRtlAcknowledgeOplockBreak(IntOplock, Stack, Irp, FALSE);
1453 
1455  return FsRtlOpBatchBreakClosePending(IntOplock, Stack, Irp);
1456 
1458  /* We can only grant level 1 if synchronous, and only a single handle to it
1459  * (plus, not a paging IO - obvious, and not cleanup done...)
1460  */
1461  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1463  {
1465  }
1466  /* Not matching, fail */
1467  else
1468  {
1469  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1472  }
1473 
1475  /* Shared can only be granted if no byte-range lock, and async operation
1476  * (plus, not a paging IO - obvious, and not cleanup done...)
1477  */
1478  if (OpenCount == 0 && !IoIsOperationSynchronous(Irp) &&
1480  {
1481  return FsRtlRequestOplockII(Oplock, Stack, Irp);
1482  }
1483  /* Not matching, fail */
1484  else
1485  {
1486  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1489  }
1490 
1492  return FsRtlAcknowledgeOplockBreak(IntOplock, Stack, Irp, TRUE);
1493 
1495  /* Batch oplock can only be granted if there's a byte-range lock and async operation
1496  * (plus, not a paging IO - obvious, and not cleanup done...)
1497  */
1498  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1500  {
1502  }
1503  /* Not matching, fail */
1504  else
1505  {
1506  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1509  }
1510 
1512  /* Filter oplock can only be granted if there's a byte-range lock and async operation
1513  * (plus, not a paging IO - obvious, and not cleanup done...)
1514  */
1515  if (OpenCount == 1 && !IoIsOperationSynchronous(Irp) &&
1517  {
1519  }
1520  /* Not matching, fail */
1521  else
1522  {
1523  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
1526  }
1527 
1528  default:
1529  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1531  return STATUS_INVALID_PARAMETER;
1532  }
1533  }
1534 
1535  /* That's a create operation! Only grant exclusive if there's a single user handle opened
1536  * and we're only performing reading operations.
1537  */
1538  if (OpenCount == 1 &&
1539  !(Stack->Parameters.Create.SecurityContext->DesiredAccess & ~(FILE_READ_ATTRIBUTES | FILE_READ_DATA)) &&
1540  (Stack->Parameters.Create.ShareAccess & FILE_SHARE_VALID_FLAGS) == FILE_SHARE_VALID_FLAGS)
1541  {
1543  }
1544 
1546 }
#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:470
#define TRUE
Definition: types.h:120
#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:356
#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
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FALSE
Definition: types.h:117
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
_In_ PIRP Irp
Definition: csq.h:116
#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:239
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:462
#define IoCompleteRequest
Definition: irp.c:1240
NTSTATUS FsRtlRequestOplockII(IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:734
#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:630
#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:2793
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define NULL
Definition: types.h:112
DWORD OpenCount
Definition: legacy.c:25
#define DPRINT
Definition: sndvol32.h:71
#define IRP_SYNCHRONOUS_PAGING_IO
#define PAGED_CODE()

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

◆ FsRtlOplockIsFastIoPossible()

BOOLEAN NTAPI FsRtlOplockIsFastIoPossible ( IN POPLOCK  Oplock)

Definition at line 1564 of file oplock.c.

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

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 283 of file oplock.c.

284 {
286 
287  DPRINT("FsRtlRemoveAndCompleteIrp(%p)\n", Irp);
288 
290 
291  /* Remove our extra ref */
292  ObDereferenceObject(Stack->FileObject);
293 
294  /* Remove our cancel routine */
295  IoAcquireCancelSpinLock(&Irp->CancelIrql);
297  IoReleaseCancelSpinLock(Irp->CancelIrql);
298 
299  /* Remove the IRP from the list it may be in (wait or shared) */
300  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
301 
302  /* And complete! */
303  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
304  Irp->IoStatus.Status = (Irp->Cancel ? STATUS_CANCELLED : STATUS_SUCCESS);
305 
307 }
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
IoSetCancelRoutine(Irp, CancelRoutine)
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
#define IoCompleteRequest
Definition: irp.c:1240
#define ObDereferenceObject
Definition: obfuncs.h:203
#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:2793
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71

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

◆ FsRtlRemoveAndCompleteWaitIrp()

VOID FsRtlRemoveAndCompleteWaitIrp ( IN PWAIT_CONTEXT  WaitCtx)

Definition at line 84 of file oplock.c.

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

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 630 of file oplock.c.

634 {
635  PINTERNAL_OPLOCK IntOplock;
636  PIRP ListIrp;
637  BOOLEAN Locked;
639 
640  DPRINT("FsRtlRequestExclusiveOplock(%p, %p, %p, %lu)\n", Oplock, Stack, Irp, Flags);
641 
642  IntOplock = *Oplock;
643  Locked = FALSE;
645 
646  /* Time to work! */
647  _SEH2_TRY
648  {
649  /* Was the oplock already allocated? If not, do it now! */
650  if (IntOplock == NULL)
651  {
652  *Oplock = FsRtlAllocateOplock();
653  IntOplock = *Oplock;
654  }
655 
656  /* Acquire our internal lock */
657  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
658  Locked = TRUE;
659 
660  /* If we request exclusiveness, a filter or a pending oplock, grant it */
662  {
663  /* Either no oplock, or pending */
664  ASSERT(BooleanFlagOn(IntOplock->Flags, (NO_OPLOCK | PENDING_LOCK)));
665  IntOplock->ExclusiveIrp = Irp;
666  IntOplock->FileObject = Stack->FileObject;
667  IntOplock->Flags = (EXCLUSIVE_LOCK | PENDING_LOCK | FILTER_OPLOCK);
668  }
669  else
670  {
671  /* Otherwise, shared or no effective oplock */
673  {
674  /* The shared IRPs list should contain a single entry! */
675  if (IntOplock->Flags == LEVEL_2_OPLOCK)
676  {
677  ListIrp = CONTAINING_RECORD(IntOplock->SharedListHead.Flink, IRP, Tail.Overlay.ListEntry);
678  ASSERT(IntOplock->SharedListHead.Flink == IntOplock->SharedListHead.Blink);
679  FsRtlRemoveAndCompleteIrp(ListIrp);
680  }
681 
682  /* Set the exclusiveness */
683  IntOplock->ExclusiveIrp = Irp;
684  IntOplock->FileObject = Stack->FileObject;
685  IntOplock->Flags = Flags;
686 
687  /* Mark the IRP pending and reference our file object */
689  ObReferenceObject(Stack->FileObject);
690  Irp->IoStatus.Information = (ULONG_PTR)IntOplock;
691 
692  /* Now, set ourselves as cancel routine */
693  IoAcquireCancelSpinLock(&Irp->CancelIrql);
694  /* Unless IRP got canceled, then, just give up */
695  if (Irp->Cancel)
696  {
697  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
698  Locked = FALSE;
701  }
702  else
703  {
705  IoReleaseCancelSpinLock(Irp->CancelIrql);
706  }
707  }
708  /* Cannot set exclusiveness, fail */
709  else
710  {
711  if (Irp != NULL)
712  {
713  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
716  }
717  }
718  }
719  }
720  /* If locked, release */
722  {
723  if (Locked)
724  {
725  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
726  }
727  }
728  _SEH2_END;
729 
730  return Status;
731 }
PFILE_OBJECT FileObject
Definition: oplock.c:35
PFAST_MUTEX IntLock
Definition: oplock.c:41
#define PENDING_LOCK
Definition: oplock.c:22
LIST_ENTRY SharedListHead
Definition: oplock.c:37
#define TRUE
Definition: types.h:120
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
#define FILTER_OPLOCK
Definition: oplock.c:18
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
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:584
_SEH2_TRY
Definition: create.c:4226
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
PIRP ExclusiveIrp
Definition: oplock.c:33
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
unsigned char BOOLEAN
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:462
#define IoCompleteRequest
Definition: irp.c:1240
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
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:44
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:283
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define NO_OPLOCK
Definition: oplock.c:15
#define EXCLUSIVE_LOCK
Definition: oplock.c:21
_SEH2_END
Definition: create.c:4400
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
#define ObReferenceObject
Definition: obfuncs.h:204
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
IoMarkIrpPending(Irp)
PINTERNAL_OPLOCK FsRtlAllocateOplock(VOID)
Definition: oplock.c:542
ULONG Flags
Definition: oplock.c:40

Referenced by FsRtlOplockFsctrl().

◆ FsRtlRequestOplockII()

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

Definition at line 734 of file oplock.c.

737 {
738  BOOLEAN Locked;
740  PINTERNAL_OPLOCK IntOplock;
741 
742  DPRINT("FsRtlRequestOplockII(%p, %p, %p)\n", Oplock, Stack, Irp);
743 
744  IntOplock = *Oplock;
745  Locked = FALSE;
747 
748  _SEH2_TRY
749  {
750  /* No oplock yet? Allocate it */
751  if (IntOplock == NULL)
752  {
753  *Oplock = FsRtlAllocateOplock();
754  IntOplock = *Oplock;
755  }
756 
757  /* Acquire the oplock */
758  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
759  Locked = TRUE;
760 
761  /* If already shared, or no oplock that's fine! */
762  if (BooleanFlagOn(IntOplock->Flags, (LEVEL_2_OPLOCK | NO_OPLOCK)))
763  {
765  /* Granted! */
766  Irp->IoStatus.Status = STATUS_SUCCESS;
767 
768  /* Insert in the shared list */
769  InsertTailList(&IntOplock->SharedListHead, &Irp->Tail.Overlay.ListEntry);
770 
771  /* Save the associated oplock */
772  Irp->IoStatus.Information = (ULONG_PTR)IntOplock;
773 
774  /* The oplock is shared */
775  IntOplock->Flags = LEVEL_2_OPLOCK;
776 
777  /* Reference the fileobject */
778  ObReferenceObject(Stack->FileObject);
779 
780  /* Set our cancel routine, unless the IRP got canceled in-between */
781  IoAcquireCancelSpinLock(&Irp->CancelIrql);
782  if (Irp->Cancel)
783  {
784  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
785  Locked = FALSE;
788  }
789  else
790  {
792  IoReleaseCancelSpinLock(Irp->CancelIrql);
793  }
794  }
795  /* Otherwise, just fail */
796  else
797  {
798  Irp->IoStatus.Status = STATUS_OPLOCK_NOT_GRANTED;
801  }
802  }
804  {
805  if (Locked)
806  {
807  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
808  }
809  }
810  _SEH2_END;
811 
812  return Status;
813 }
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY SharedListHead
Definition: oplock.c:37
#define TRUE
Definition: types.h:120
#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:4226
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
unsigned char BOOLEAN
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:462
#define IoCompleteRequest
Definition: irp.c:1240
Status
Definition: gdiplustypes.h:24
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
#define NO_OPLOCK
Definition: oplock.c:15
_SEH2_END
Definition: create.c:4400
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
#define ObReferenceObject
Definition: obfuncs.h:204
#define ULONG_PTR
Definition: config.h:101
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
IoMarkIrpPending(Irp)
VOID NTAPI FsRtlCancelOplockIIIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:311
PINTERNAL_OPLOCK FsRtlAllocateOplock(VOID)
Definition: oplock.c:542
ULONG Flags
Definition: oplock.c:40

Referenced by FsRtlOplockFsctrl().

◆ FsRtlUninitializeOplock()

VOID NTAPI FsRtlUninitializeOplock ( IN POPLOCK  Oplock)

Definition at line 1600 of file oplock.c.

1601 {
1602  PINTERNAL_OPLOCK IntOplock;
1603  PLIST_ENTRY NextEntry;
1604  PWAIT_CONTEXT WaitCtx;
1605  PIRP Irp;
1607 
1608  DPRINT("FsRtlUninitializeOplock(%p)\n", Oplock);
1609 
1610  IntOplock = *Oplock;
1611 
1612  /* No oplock, nothing to do */
1613  if (IntOplock == NULL)
1614  {
1615  return;
1616  }
1617 
1618  /* Caller won't have the oplock anymore */
1619  *Oplock = NULL;
1620 
1621  _SEH2_TRY
1622  {
1623  ExAcquireFastMutexUnsafe(IntOplock->IntLock);
1624 
1625  /* If we had IRPs waiting for the lock, complete them */
1626  for (NextEntry = IntOplock->WaitListHead.Flink;
1627  NextEntry != &IntOplock->WaitListHead;
1628  NextEntry = NextEntry->Flink)
1629  {
1630  WaitCtx = CONTAINING_RECORD(NextEntry, WAIT_CONTEXT, WaitListEntry);
1631  Irp = WaitCtx->Irp;
1632 
1633  RemoveEntryList(&WaitCtx->WaitListEntry);
1634  /* Remove the cancel routine */
1635  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1637  IoReleaseCancelSpinLock(Irp->CancelIrql);
1638 
1639  /* And complete */
1640  Irp->IoStatus.Information = 0;
1641  WaitCtx->CompletionRoutine(WaitCtx->CompletionContext, WaitCtx->Irp);
1642 
1643  ExFreePoolWithTag(WaitCtx, TAG_OPLOCK);
1644  }
1645 
1646  /* If we had shared IRPs (LEVEL_2), complete them */
1647  for (NextEntry = IntOplock->SharedListHead.Flink;
1648  NextEntry != &IntOplock->SharedListHead;
1649  NextEntry = NextEntry->Flink)
1650  {
1651  Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
1652 
1653  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
1654 
1655  /* Remvoe the cancel routine */
1656  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1658  IoReleaseCancelSpinLock(Irp->CancelIrql);
1659 
1660  /* Dereference the file object */
1662  ObDereferenceObject(Stack->FileObject);
1663 
1664  /* And complete */
1665  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1666  Irp->IoStatus.Status = STATUS_SUCCESS;
1668  }
1669 
1670  /* If we have an exclusive IRP, complete it */
1671  Irp = IntOplock->ExclusiveIrp;
1672  if (Irp != NULL)
1673  {
1674  /* Remvoe the cancel routine */
1675  IoAcquireCancelSpinLock(&Irp->CancelIrql);
1677  IoReleaseCancelSpinLock(Irp->CancelIrql);
1678 
1679  /* And complete */
1680  Irp->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
1681  Irp->IoStatus.Status = STATUS_SUCCESS;
1683  IntOplock->ExclusiveIrp = NULL;
1684 
1685  /* If still referenced, dereference */
1686  if (IntOplock->FileObject != NULL)
1687  {
1688  ObDereferenceObject(IntOplock->FileObject);
1689  }
1690  }
1691  }
1693  {
1694  ExReleaseFastMutexUnsafe(IntOplock->IntLock);
1695  }
1696  _SEH2_END;
1697 
1698  ExFreePoolWithTag(IntOplock->IntLock, TAG_OPLOCK);
1699  ExFreePoolWithTag(IntOplock, TAG_OPLOCK);
1700 }
PFILE_OBJECT FileObject
Definition: oplock.c:35
PVOID CompletionContext
Definition: oplock.c:49
PFAST_MUTEX IntLock
Definition: oplock.c:41
LIST_ENTRY SharedListHead
Definition: oplock.c:37
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
LIST_ENTRY WaitListHead
Definition: oplock.c:39
#define TAG_OPLOCK
Definition: tag.h:49
IoSetCancelRoutine(Irp, CancelRoutine)
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
_SEH2_TRY
Definition: create.c:4226
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
PIRP ExclusiveIrp
Definition: oplock.c:33
_In_ PIRP Irp
Definition: csq.h:116
#define IoCompleteRequest
Definition: irp.c:1240
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:121
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
LIST_ENTRY WaitListEntry
Definition: oplock.c:46
#define ObDereferenceObject
Definition: obfuncs.h:203
Definition: typedefs.h:119
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: oplock.c:48
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_SEH2_END
Definition: create.c:4400
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
PIRP Irp
Definition: oplock.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
#define FILE_OPLOCK_BROKEN_TO_NONE
#define DPRINT
Definition: sndvol32.h:71
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099

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 148 of file oplock.c.

154 {
155  BOOLEAN Locked;
156  PWAIT_CONTEXT WaitCtx;
157 
158  DPRINT("FsRtlWaitOnIrp(%p, %p, %p, %p, %p, %p)\n", Oplock, Irp, CompletionContext, CompletionRoutine, PostIrpRoutine, WaitEvent);
159 
160  /* We must always be called with IntLock locked! */
161  Locked = TRUE;
162  /* Dirty check for above statement */
163  ASSERT(Oplock->IntLock->Owner == KeGetCurrentThread());
164 
165  /* Allocate a wait context for the IRP */
167  WaitCtx->Irp = Irp;
168  WaitCtx->SavedInformation = Irp->IoStatus.Information;
169  /* If caller provided everything required, us it */
170  if (CompletionRoutine != NULL)
171  {
174  }
175  /* Otherwise, put ourselves */
176  else
177  {
179  WaitCtx->CompletionContext = WaitEvent;
181  }
182 
183  /* If we got a prepost routine, call it now! */
184  if (PostIrpRoutine != NULL)
185  {
187  }
188 
189  Irp->IoStatus.Status = STATUS_SUCCESS;
190 
191  /* Queue the IRP - it's OK, we're locked */
192  InsertHeadList(&Oplock->WaitListHead, &WaitCtx->WaitListEntry);
193 
194  /* Set the oplock as information of the IRP (for the cancel routine)
195  * And lock the cancel routine lock for setting it
196  */
197  IoAcquireCancelSpinLock(&Irp->CancelIrql);
198  Irp->IoStatus.Information = (ULONG_PTR)Oplock;
199 
200  /* If there's already a cancel routine
201  * Cancel the IRP
202  */
203  if (Irp->Cancel)
204  {
205  ExReleaseFastMutexUnsafe(Oplock->IntLock);
206  Locked = FALSE;
207 
208  if (CompletionRoutine != NULL)
209  {
211  }
213  }
214  /* Otherwise, put ourselves as the cancel routine and start waiting */
215  else
216  {
218  IoReleaseCancelSpinLock(Irp->CancelIrql);
219  if (CompletionRoutine != NULL)
220  {
222  }
223  else
224  {
225  ExReleaseFastMutexUnsafe(Oplock->IntLock);
226  Locked = FALSE;
228  }
229  }
230 
231  /* If we didn't unlock yet, do it now */
232  if (Locked)
233  {
234  ExReleaseFastMutexUnsafe(Oplock->IntLock);
235  }
236 }
PVOID CompletionContext
Definition: oplock.c:49
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE _In_opt_ __drv_aliasesMem WDFCONTEXT CompletionContext
Definition: wdfrequest.h:893
#define TRUE
Definition: types.h:120
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: tag.h:49
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:51
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:207
VOID NTAPI FsRtlCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:114
unsigned char BOOLEAN
#define ASSERT(a)
Definition: mode.c:44
LIST_ENTRY WaitListEntry
Definition: oplock.c:46
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: oplock.c:48
VOID NTAPI FsRtlCompletionRoutinePriv(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:69
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
#define NULL
Definition: types.h:112
PIRP Irp
Definition: oplock.c:47
#define ULONG_PTR
Definition: config.h:101
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
#define KeGetCurrentThread
Definition: hal.h:55
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().