ReactOS 0.4.15-dev-7887-g64a59a1
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) \
_In_ PIRP Irp
Definition: csq.h:116
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE _In_opt_ POPLOCK_FS_PREPOST_IRP PostIrpRoutine
Definition: fsrtlfuncs.h:676
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
#define LEVEL_2_OPLOCK
Definition: oplock.c:19
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895

◆ BreakToNoneIfRequired

#define BreakToNoneIfRequired
Value:
if (IntOplock->Flags == LEVEL_2_OPLOCK || IntOplock->FileObject != Stack->FileObject) \
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

◆ 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;
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}
unsigned char BOOLEAN
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
#define InsertTailList(ListHead, Entry)
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
@ Unknown
Definition: i8042prt.h:114
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
#define ASSERT(a)
Definition: mode.c:44
_In_ PMEMORY_AREA _In_ PVOID _In_ BOOLEAN Locked
Definition: newmm.h:209
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
VOID FASTCALL IofCompleteRequest(IN PIRP Irp, IN CCHAR PriorityBoost)
Definition: irp.c:1308
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1882
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
#define STATUS_INVALID_OPLOCK_PROTOCOL
Definition: ntstatus.h:463
#define BROKEN_TO_NONE
Definition: oplock.c:25
#define NO_OPLOCK
Definition: oplock.c:15
#define BROKEN_TO_NONE_FROM_LEVEL_2
Definition: oplock.c:26
#define BROKEN_TO_LEVEL_2
Definition: oplock.c:24
VOID FsRtlRemoveAndCompleteWaitIrp(IN PWAIT_CONTEXT WaitCtx)
Definition: oplock.c:84
VOID NTAPI FsRtlCancelOplockIIIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:311
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FILE_OPLOCK_BROKEN_TO_NONE
#define ObDereferenceObject
Definition: obfuncs.h:203

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
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 {
573 Oplock = NULL;
574 }
575 }
576 }
577 _SEH2_END;
578
579 return Oplock;
580}
#define PAGED_CODE()
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
ULONG Flags
Definition: oplock.c:40
LIST_ENTRY SharedListHead
Definition: oplock.c:37
LIST_ENTRY WaitListHead
Definition: oplock.c:39
PFAST_MUTEX IntLock
Definition: oplock.c:41
#define TAG_OPLOCK
Definition: tag.h:51
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
FAST_MUTEX
Definition: extypes.h:17
#define POOL_COLD_ALLOCATION
#define POOL_RAISE_IF_ALLOCATION_FAILURE

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 */
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! */
627}
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
struct _INTERNAL_OPLOCK * PINTERNAL_OPLOCK
PIRP ExclusiveIrp
Definition: oplock.c:33
PFILE_OBJECT FileObject
Definition: oplock.c:35
IO_STATUS_BLOCK IoStatus
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

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;
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 {
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 */
353}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
@ Removed
Definition: fbtusb.h:86
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
VOID FsRtlRemoveAndCompleteIrp(IN PIRP Irp)
Definition: oplock.c:283

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 */
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 }
145}
PIRP Irp
Definition: oplock.c:47

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 }
1322 {
1324
1325 return STATUS_SUCCESS;
1326 }
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}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define FILE_SHARE_READ
Definition: compat.h:136
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileLinkInformation
Definition: from_kernel.h:72
@ FileAllocationInformation
Definition: from_kernel.h:80
@ FileShortNameInformation
Definition: from_kernel.h:101
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_RESERVE_OPFILTER
Definition: from_kernel.h:45
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_READ_EA
Definition: nt_native.h:638
#define FILE_EXECUTE
Definition: nt_native.h:642
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define READ_CONTROL
Definition: nt_native.h:58
#define BATCH_OPLOCK
Definition: oplock.c:17
VOID FsRtlOplockCleanup(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack)
Definition: oplock.c:816
#define FILTER_OPLOCK
Definition: oplock.c:18
#define BreakToNoneIfRequired
#define BreakToIIIfRequired
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define FSCTL_SET_ZERO_DATA
Definition: winioctl.h:141
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG _Out_opt_ PULONG CreateDisposition
Definition: wdfregistry.h:120
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_PAGING_IO
#define IRP_MJ_FLUSH_BUFFERS
#define IRP_MJ_CLEANUP

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}
#define PKEVENT
Definition: env_spec_w32.h:70
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define IO_NO_INCREMENT
Definition: iotypes.h:598

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 &&
1377 {
1378 return TRUE;
1379 }
1380
1381 return FALSE;
1382}

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}

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}

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}
LONG NTSTATUS
Definition: precomp.h:26
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
Status
Definition: gdiplustypes.h:25
#define PENDING_LOCK
Definition: oplock.c:22
#define BROKEN_ANY
Definition: oplock.c:28
#define LEVEL_1_OPLOCK
Definition: oplock.c:16
#define BROKEN_TO_CLOSE_PENDING
Definition: oplock.c:27

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}
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
VOID NTAPI FsRtlNotifyCompletion(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:56

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 {
1128
1129 ExReleaseFastMutexUnsafe(Oplock->IntLock);
1130
1131 return STATUS_SUCCESS;
1132 }
1133 else
1134 {
1135 ExReleaseFastMutexUnsafe(Oplock->IntLock);
1137 }
1138}
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
#define EXCLUSIVE_LOCK
Definition: oplock.c:21
#define FILE_OPLOCK_BROKEN_TO_LEVEL_2

◆ 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);
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 {
1020
1021 ExReleaseFastMutexUnsafe(Oplock->IntLock);
1022
1023 return STATUS_SUCCESS;
1024 }
1025 /* Done */
1026 else
1027 {
1028 ExReleaseFastMutexUnsafe(Oplock->IntLock);
1030 }
1031}

◆ 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 {
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}
PFILE_OBJECT FileObject
Definition: iotypes.h:3169

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;
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}
DWORD OpenCount
Definition: legacy.c:25
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define FILE_SHARE_VALID_FLAGS
Definition: nt_native.h:683
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define STATUS_OPLOCK_NOT_GRANTED
Definition: ntstatus.h:462
NTSTATUS FsRtlOpBatchBreakClosePending(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:470
NTSTATUS FsRtlOplockBreakNotify(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:239
NTSTATUS FsRtlAcknowledgeOplockBreak(IN PINTERNAL_OPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN BOOLEAN SwitchToLevel2)
Definition: oplock.c:356
NTSTATUS FsRtlRequestExclusiveOplock(IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp, IN ULONG Flags)
Definition: oplock.c:630
NTSTATUS FsRtlRequestOplockII(IN POPLOCK Oplock, IN PIO_STACK_LOCATION Stack, IN PIRP Irp)
Definition: oplock.c:734
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define IRP_SYNCHRONOUS_PAGING_IO

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 &&
1577 {
1578 return FALSE;
1579 }
1580
1581 return TRUE;
1582}

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}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

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 */
110}

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;
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! */
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 */
658 Locked = TRUE;
659
660 /* If we request exclusiveness, a filter or a pending oplock, grant it */
662 {
663 /* Either no oplock, or pending */
665 IntOplock->ExclusiveIrp = Irp;
666 IntOplock->FileObject = Stack->FileObject;
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);
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 {
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 {
726 }
727 }
728 _SEH2_END;
729
730 return Status;
731}
VOID NTAPI FsRtlCancelExclusiveIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:584
PINTERNAL_OPLOCK FsRtlAllocateOplock(VOID)
Definition: oplock.c:542
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ObReferenceObject
Definition: obfuncs.h:204

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{
740 PINTERNAL_OPLOCK IntOplock;
741
742 DPRINT("FsRtlRequestOplockII(%p, %p, %p)\n", Oplock, Stack, Irp);
743
744 IntOplock = *Oplock;
745 Locked = FALSE;
747
749 {
750 /* No oplock yet? Allocate it */
751 if (IntOplock == NULL)
752 {
753 *Oplock = FsRtlAllocateOplock();
754 IntOplock = *Oplock;
755 }
756
757 /* Acquire the oplock */
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 {
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 {
808 }
809 }
810 _SEH2_END;
811
812 return Status;
813}

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 {
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 {
1695 }
1696 _SEH2_END;
1697
1699 ExFreePoolWithTag(IntOplock, TAG_OPLOCK);
1700}
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: oplock.c:48
PVOID CompletionContext
Definition: oplock.c:49
LIST_ENTRY WaitListEntry
Definition: oplock.c:46

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{
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}
#define InsertHeadList(ListHead, Entry)
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeGetCurrentThread
Definition: hal.h:55
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
VOID NTAPI FsRtlCancelWaitIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: oplock.c:114
VOID NTAPI FsRtlCompletionRoutinePriv(IN PVOID Context, IN PIRP Irp)
Definition: oplock.c:69
ULONG_PTR SavedInformation
Definition: oplock.c:51
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE _In_opt_ __drv_aliasesMem WDFCONTEXT CompletionContext
Definition: wdfrequest.h:898
@ Executive
Definition: ketypes.h:415

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