3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module implements the Lock Control routines for Fat called
12 by the dispatch driver.
20 // The local debug trace level
23 #define Dbg (DEBUG_TRACE_LOCKCTRL)
26 #pragma alloc_text(PAGE, FatCommonLockControl)
27 #pragma alloc_text(PAGE, FatFastLock)
28 #pragma alloc_text(PAGE, FatFastUnlockAll)
29 #pragma alloc_text(PAGE, FatFastUnlockAllByKey)
30 #pragma alloc_text(PAGE, FatFastUnlockSingle)
31 #pragma alloc_text(PAGE, FatFsdLockControl)
35 _Function_class_(IRP_MJ_LOCK_CONTROL
)
36 _Function_class_(DRIVER_DISPATCH
)
40 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject
,
48 This routine implements the FSD part of Lock control operations
52 VolumeDeviceObject - Supplies the volume device object where the
55 Irp - Supplies the Irp being processed
59 NTSTATUS - The FSD status for the IRP
65 PIRP_CONTEXT IrpContext
= NULL
;
71 DebugTrace(+1, Dbg
, "FatFsdLockControl\n", 0);
74 // Call the common Lock Control routine, with blocking allowed if
78 FsRtlEnterFileSystem();
80 TopLevel
= FatIsIrpTopLevel( Irp
);
84 IrpContext
= FatCreateIrpContext( Irp
, CanFsdWait( Irp
) );
86 Status
= FatCommonLockControl( IrpContext
, Irp
);
88 } _SEH2_EXCEPT(FatExceptionFilter( IrpContext
, _SEH2_GetExceptionInformation() )) {
91 // We had some trouble trying to perform the requested
92 // operation, so we'll abort the I/O request with
93 // the error status that we get back from the
97 Status
= FatProcessException( IrpContext
, Irp
, _SEH2_GetExceptionCode() );
100 if (TopLevel
) { IoSetTopLevelIrp( NULL
); }
102 FsRtlExitFileSystem();
105 // And return to our caller
108 DebugTrace(-1, Dbg
, "FatFsdLockControl -> %08lx\n", Status
);
110 UNREFERENCED_PARAMETER( VolumeDeviceObject
);
116 _Function_class_(FAST_IO_LOCK
)\f
120 IN PFILE_OBJECT FileObject
,
121 IN PLARGE_INTEGER FileOffset
,
122 IN PLARGE_INTEGER Length
,
125 BOOLEAN FailImmediately
,
126 BOOLEAN ExclusiveLock
,
127 OUT PIO_STATUS_BLOCK IoStatus
,
128 IN PDEVICE_OBJECT DeviceObject
135 This is a call back routine for doing the fast lock call.
139 FileObject - Supplies the file object used in this operation
141 FileOffset - Supplies the file offset used in this operation
143 Length - Supplies the length used in this operation
145 ProcessId - Supplies the process ID used in this operation
147 Key - Supplies the key used in this operation
149 FailImmediately - Indicates if the request should fail immediately
150 if the lock cannot be granted.
152 ExclusiveLock - Indicates if this is a request for an exclusive or
155 IoStatus - Receives the Status if this operation is successful
159 BOOLEAN - TRUE if this operation completed and FALSE if caller
160 needs to take the long route.
165 BOOLEAN Results
= FALSE
;
171 UNREFERENCED_PARAMETER( DeviceObject
);
173 DebugTrace(+1, Dbg
, "FatFastLock\n", 0);
176 // Decode the type of file object we're being asked to process and make
177 // sure it is only a user file open.
180 if (FatDecodeFileObject( FileObject
, &Vcb
, &Fcb
, &Ccb
) != UserFileOpen
) {
182 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
183 IoStatus
->Information
= 0;
185 DebugTrace(-1, Dbg
, "FatFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
190 // Acquire shared access to the Fcb
193 FsRtlEnterFileSystem();
194 ExAcquireResourceSharedLite( Fcb
->Header
.Resource
, TRUE
);
199 // We check whether we can proceed
200 // based on the state of the file oplocks.
203 if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb
) )) {
205 try_return( Results
= FALSE
);
209 // Now call the FsRtl routine to do the actual processing of the
214 #pragma prefast( suppress:28159, "prefast indicates this API is obsolete but it is ok for fastfat to continue using it" )
216 Results
= FsRtlFastLock( &Fcb
->Specific
.Fcb
.FileLock
,
231 // Set the flag indicating if Fast I/O is possible
234 Fcb
->Header
.IsFastIoPossible
= FatIsFastIoPossible( Fcb
);
240 DebugUnwind( FatFastLock
);
243 // Release the Fcb, and return to our caller
246 ExReleaseResourceLite( Fcb
->Header
.Resource
);
247 FsRtlExitFileSystem();
249 DebugTrace(-1, Dbg
, "FatFastLock -> %08lx\n", Results
);
256 _Function_class_(FAST_IO_UNLOCK_SINGLE
)\f
259 FatFastUnlockSingle (
260 IN PFILE_OBJECT FileObject
,
261 IN PLARGE_INTEGER FileOffset
,
262 IN PLARGE_INTEGER Length
,
265 OUT PIO_STATUS_BLOCK IoStatus
,
266 IN PDEVICE_OBJECT DeviceObject
273 This is a call back routine for doing the fast unlock single call.
277 FileObject - Supplies the file object used in this operation
279 FileOffset - Supplies the file offset used in this operation
281 Length - Supplies the length used in this operation
283 ProcessId - Supplies the process ID used in this operation
285 Key - Supplies the key used in this operation
287 Status - Receives the Status if this operation is successful
291 BOOLEAN - TRUE if this operation completed and FALSE if caller
292 needs to take the long route.
297 BOOLEAN Results
= FALSE
;
303 UNREFERENCED_PARAMETER( DeviceObject
);
305 DebugTrace(+1, Dbg
, "FatFastUnlockSingle\n", 0);
307 IoStatus
->Information
= 0;
310 // Decode the type of file object we're being asked to process and make sure
311 // it is only a user file open
314 if (FatDecodeFileObject( FileObject
, &Vcb
, &Fcb
, &Ccb
) != UserFileOpen
) {
316 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
318 DebugTrace(-1, Dbg
, "FatFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
323 // Acquire exclusive access to the Fcb this operation can always wait
326 FsRtlEnterFileSystem();
331 // We check whether we can proceed based on the state of the file oplocks.
334 if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb
) )) {
336 try_return( Results
= FALSE
);
340 // Now call the FsRtl routine to do the actual processing of the
341 // Lock request. The call will always succeed.
345 IoStatus
->Status
= FsRtlFastUnlockSingle( &Fcb
->Specific
.Fcb
.FileLock
,
355 // Set the flag indicating if Fast I/O is possible
358 Fcb
->Header
.IsFastIoPossible
= FatIsFastIoPossible( Fcb
);
363 DebugUnwind( FatFastUnlockSingle
);
366 // Release the Fcb, and return to our caller
369 FsRtlExitFileSystem();
371 DebugTrace(-1, Dbg
, "FatFastUnlockSingle -> %08lx\n", Results
);
378 _Function_class_(FAST_IO_UNLOCK_ALL
)\f
382 IN PFILE_OBJECT FileObject
,
384 OUT PIO_STATUS_BLOCK IoStatus
,
385 IN PDEVICE_OBJECT DeviceObject
392 This is a call back routine for doing the fast unlock all call.
396 FileObject - Supplies the file object used in this operation
398 ProcessId - Supplies the process ID used in this operation
400 Status - Receives the Status if this operation is successful
404 BOOLEAN - TRUE if this operation completed and FALSE if caller
405 needs to take the long route.
410 BOOLEAN Results
= FALSE
;
416 UNREFERENCED_PARAMETER( DeviceObject
);
418 DebugTrace(+1, Dbg
, "FatFastUnlockAll\n", 0);
420 IoStatus
->Information
= 0;
423 // Decode the type of file object we're being asked to process and make sure
424 // it is only a user file open.
427 if (FatDecodeFileObject( FileObject
, &Vcb
, &Fcb
, &Ccb
) != UserFileOpen
) {
429 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
431 DebugTrace(-1, Dbg
, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
436 // Acquire exclusive access to the Fcb this operation can always wait
439 FsRtlEnterFileSystem();
441 (VOID
) ExAcquireResourceSharedLite( Fcb
->Header
.Resource
, TRUE
);
446 // We check whether we can proceed based on the state of the file oplocks.
449 if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb
) )) {
451 try_return( Results
= FALSE
);
455 // Now call the FsRtl routine to do the actual processing of the
456 // Lock request. The call will always succeed.
460 IoStatus
->Status
= FsRtlFastUnlockAll( &Fcb
->Specific
.Fcb
.FileLock
,
466 // Set the flag indicating if Fast I/O is possible
469 Fcb
->Header
.IsFastIoPossible
= FatIsFastIoPossible( Fcb
);
474 DebugUnwind( FatFastUnlockAll
);
477 // Release the Fcb, and return to our caller
480 ExReleaseResourceLite( (Fcb
)->Header
.Resource
);
482 FsRtlExitFileSystem();
484 DebugTrace(-1, Dbg
, "FatFastUnlockAll -> %08lx\n", Results
);
491 _Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY
)
494 FatFastUnlockAllByKey (
495 IN PFILE_OBJECT FileObject
,
498 OUT PIO_STATUS_BLOCK IoStatus
,
499 IN PDEVICE_OBJECT DeviceObject
506 This is a call back routine for doing the fast unlock all by key call.
510 FileObject - Supplies the file object used in this operation
512 ProcessId - Supplies the process ID used in this operation
514 Key - Supplies the key used in this operation
516 Status - Receives the Status if this operation is successful
520 BOOLEAN - TRUE if this operation completed and FALSE if caller
521 needs to take the long route.
526 BOOLEAN Results
= FALSE
;
532 UNREFERENCED_PARAMETER( DeviceObject
);
534 DebugTrace(+1, Dbg
, "FatFastUnlockAllByKey\n", 0);
536 IoStatus
->Information
= 0;
539 // Decode the type of file object we're being asked to process and make sure
540 // it is only a user file open.
543 if (FatDecodeFileObject( FileObject
, &Vcb
, &Fcb
, &Ccb
) != UserFileOpen
) {
545 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
547 DebugTrace(-1, Dbg
, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
552 // Acquire exclusive access to the Fcb this operation can always wait
555 FsRtlEnterFileSystem();
557 (VOID
) ExAcquireResourceSharedLite( Fcb
->Header
.Resource
, TRUE
);
562 // We check whether we can proceed based on the state of the file oplocks.
565 if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb
) )) {
567 try_return( Results
= FALSE
);
571 // Now call the FsRtl routine to do the actual processing of the
572 // Lock request. The call will always succeed.
576 IoStatus
->Status
= FsRtlFastUnlockAllByKey( &Fcb
->Specific
.Fcb
.FileLock
,
583 // Set the flag indicating if Fast I/O is possible
586 Fcb
->Header
.IsFastIoPossible
= FatIsFastIoPossible( Fcb
);
591 DebugUnwind( FatFastUnlockAllByKey
);
594 // Release the Fcb, and return to our caller
597 ExReleaseResourceLite( (Fcb
)->Header
.Resource
);
599 FsRtlExitFileSystem();
601 DebugTrace(-1, Dbg
, "FatFastUnlockAllByKey -> %08lx\n", Results
);
608 _Requires_lock_held_(_Global_critical_region_
)
610 FatCommonLockControl (
611 IN PIRP_CONTEXT IrpContext
,
619 This is the common routine for doing Lock control operations called
620 by both the fsd and fsp threads
624 Irp - Supplies the Irp to process
628 NTSTATUS - The return status for the operation
633 NTSTATUS Status
= STATUS_SUCCESS
;
634 PIO_STACK_LOCATION IrpSp
;
636 TYPE_OF_OPEN TypeOfOpen
;
642 BOOLEAN OplockPostIrp
= FALSE
;
647 // Get a pointer to the current Irp stack location
650 IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
652 DebugTrace(+1, Dbg
, "FatCommonLockControl\n", 0);
653 DebugTrace( 0, Dbg
, "Irp = %p\n", Irp
);
654 DebugTrace( 0, Dbg
, "MinorFunction = %08lx\n", IrpSp
->MinorFunction
);
657 // Decode the type of file object we're being asked to process
660 TypeOfOpen
= FatDecodeFileObject( IrpSp
->FileObject
, &Vcb
, &Fcb
, &Ccb
);
663 // If the file is not a user file open then we reject the request
664 // as an invalid parameter
667 if (TypeOfOpen
!= UserFileOpen
) {
669 FatCompleteRequest( IrpContext
, Irp
, STATUS_INVALID_PARAMETER
);
671 DebugTrace(-1, Dbg
, "FatCommonLockControl -> STATUS_INVALID_PARAMETER\n", 0);
672 return STATUS_INVALID_PARAMETER
;
676 // Acquire exclusive access to the Fcb and enqueue the Irp if we didn't
680 if (!FatAcquireSharedFcb( IrpContext
, Fcb
)) {
682 Status
= FatFsdPostRequest( IrpContext
, Irp
);
684 DebugTrace(-1, Dbg
, "FatCommonLockControl -> %08lx\n", Status
);
691 // We check whether we can proceed
692 // based on the state of the file oplocks.
695 #if (NTDDI_VERSION >= NTDDI_WIN8)
697 if (((IRP_MN_LOCK
== IrpSp
->MinorFunction
) &&
698 ((ULONGLONG
)IrpSp
->Parameters
.LockControl
.ByteOffset
.QuadPart
<
699 (ULONGLONG
)Fcb
->Header
.AllocationSize
.QuadPart
)) ||
700 ((IRP_MN_LOCK
!= IrpSp
->MinorFunction
) &&
701 FsRtlAreThereWaitingFileLocks( &Fcb
->Specific
.Fcb
.FileLock
))) {
704 // Check whether we can proceed based on the state of file oplocks if doing
705 // an operation that interferes with oplocks. Those operations are:
707 // 1. Lock a range within the file's AllocationSize.
708 // 2. Unlock a range when there are waiting locks on the file. This one
709 // is not guaranteed to interfere with oplocks, but it could, as
710 // unlocking this range might cause a waiting lock to be granted
711 // within AllocationSize!
715 Status
= FsRtlCheckOplock( FatGetFcbOplock(Fcb
),
721 #if (NTDDI_VERSION >= NTDDI_WIN8)
725 if (Status
!= STATUS_SUCCESS
) {
727 OplockPostIrp
= TRUE
;
728 try_return( NOTHING
);
732 // Now call the FsRtl routine to do the actual processing of the
736 Status
= FsRtlProcessFileLock( &Fcb
->Specific
.Fcb
.FileLock
, Irp
, NULL
);
739 // Set the flag indicating if Fast I/O is possible
742 Fcb
->Header
.IsFastIoPossible
= FatIsFastIoPossible( Fcb
);
747 DebugUnwind( FatCommonLockControl
);
750 // Only if this is not an abnormal termination do we delete the
754 if (!_SEH2_AbnormalTermination() && !OplockPostIrp
) {
756 FatCompleteRequest( IrpContext
, FatNull
, 0 );
760 // Release the Fcb, and return to our caller
763 FatReleaseFcb( IrpContext
, Fcb
);
765 DebugTrace(-1, Dbg
, "FatCommonLockControl -> %08lx\n", Status
);