1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
8 * File: LockCtrl.cpp.cpp
10 * Module: UDF File System Driver (Kernel mode execution only)
13 * Contains code to handle the "byte-range locking" dispatch entry point.
15 *************************************************************************/
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN
23 /*************************************************************************
25 * Function: UDFLockControl()
29 * Expected Interrupt Level (for execution) :
33 * Return Value: Irrelevant.
35 *************************************************************************/
39 IN PDEVICE_OBJECT DeviceObject
, // the logical volume device object
40 IN PIRP Irp
) // I/O Request Packet
42 NTSTATUS RC
= STATUS_SUCCESS
;
43 PtrUDFIrpContext PtrIrpContext
= NULL
;
44 BOOLEAN AreWeTopLevel
= FALSE
;
46 UDFPrint(("UDFLockControl\n"));
49 FsRtlEnterFileSystem();
53 // set the top level context
54 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
55 // Call the common Lock Control routine, with blocking allowed if
59 // get an IRP context structure and issue the request
60 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
62 RC
= UDFCommonLockControl(PtrIrpContext
, Irp
);
64 RC
= STATUS_INSUFFICIENT_RESOURCES
;
65 Irp
->IoStatus
.Status
= RC
;
66 Irp
->IoStatus
.Information
= 0;
68 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
71 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
73 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
75 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
79 IoSetTopLevelIrp(NULL
);
82 FsRtlExitFileSystem();
85 } // end UDFLockControl()
88 /*************************************************************************
90 * Function: UDFCommonLockControl()
93 * This is the common routine for doing Lock control operations called
94 * by both the fsd and fsp threads
96 * Expected Interrupt Level (for execution) :
100 * Return Value: Irrelevant
102 *************************************************************************/
105 UDFCommonLockControl(
106 IN PtrUDFIrpContext PtrIrpContext
,
109 NTSTATUS RC
= STATUS_SUCCESS
;
110 PIO_STACK_LOCATION IrpSp
= NULL
;
111 //IO_STATUS_BLOCK LocalIoStatus;
112 // BOOLEAN CompleteRequest = FALSE;
113 BOOLEAN PostRequest
= FALSE
;
114 BOOLEAN CanWait
= FALSE
;
115 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
116 BOOLEAN AcquiredFCB
= FALSE
;
117 PFILE_OBJECT FileObject
= NULL
;
118 PtrUDFFCB Fcb
= NULL
;
119 PtrUDFCCB Ccb
= NULL
;
121 UDFPrint(("UDFCommonLockControl\n"));
124 // First, get a pointer to the current I/O stack location.
125 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
128 FileObject
= IrpSp
->FileObject
;
131 // Get the FCB and CCB pointers.
132 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
136 // Validate the sent-in FCB
137 if ( (Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
138 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
140 // CompleteRequest = TRUE;
141 try_return(RC
= STATUS_INVALID_PARAMETER
);
144 NtReqFcb
= Fcb
->NTRequiredFCB
;
145 CanWait
= ((PtrIrpContext
->IrpContextFlags
& UDF_IRP_CONTEXT_CAN_BLOCK
) ? TRUE
: FALSE
);
147 // Acquire the FCB resource shared
148 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
149 if (!UDFAcquireResourceExclusive(&(NtReqFcb
->MainResource
), CanWait
)) {
151 try_return(RC
= STATUS_PENDING
);
155 RC
= FsRtlProcessFileLock(&(NtReqFcb
->FileLock
), Irp
, NULL
);
156 // CompleteRequest = TRUE;
162 // Release the FCB resources if acquired.
164 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb
);
165 UDFReleaseResource(&(NtReqFcb
->MainResource
));
169 // Perform appropriate post related processing here
170 RC
= UDFPostRequest(PtrIrpContext
, Irp
);
172 if(!_SEH2_AbnormalTermination()) {
173 // Simply free up the IrpContext since the IRP has been queued or
174 // Completed by FsRtlProcessFileLock
175 UDFReleaseIrpContext(PtrIrpContext
);
177 } _SEH2_END
; // end of "__finally" processing
180 } // end UDFCommonLockControl()
185 This is a call back routine for doing the fast lock call.
187 FileObject - Supplies the file object used in this operation
188 FileOffset - Supplies the file offset used in this operation
189 Length - Supplies the length used in this operation
190 ProcessId - Supplies the process ID used in this operation
191 Key - Supplies the key used in this operation
192 FailImmediately - Indicates if the request should fail immediately
193 if the lock cannot be granted.
194 ExclusiveLock - Indicates if this is a request for an exclusive or
196 IoStatus - Receives the Status if this operation is successful
199 BOOLEAN - TRUE if this operation completed and FALSE if caller
200 needs to take the long route.
206 IN PFILE_OBJECT FileObject
,
207 IN PLARGE_INTEGER FileOffset
,
208 IN PLARGE_INTEGER Length
,
211 BOOLEAN FailImmediately
,
212 BOOLEAN ExclusiveLock
,
213 OUT PIO_STATUS_BLOCK IoStatus
,
214 IN PDEVICE_OBJECT DeviceObject
217 BOOLEAN Results
= FALSE
;
219 // BOOLEAN AcquiredFCB = FALSE;
220 PtrUDFFCB Fcb
= NULL
;
221 PtrUDFCCB Ccb
= NULL
;
223 UDFPrint(("UDFFastLock\n"));
224 // Decode the type of file object we're being asked to process and make
225 // sure it is only a user file open.
228 // Get the FCB and CCB pointers.
229 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
233 // Validate the sent-in FCB
234 if ( (Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
235 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
237 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
238 IoStatus
->Information
= 0;
242 // Acquire exclusive access to the Fcb this operation can always wait
244 FsRtlEnterFileSystem();
247 // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE );
251 // We check whether we can proceed
252 // based on the state of the file oplocks.
254 // Now call the FsRtl routine to do the actual processing of the
256 if ((Results
= FsRtlFastLock( &(Fcb
->NTRequiredFCB
->FileLock
),
268 // Set the flag indicating if Fast I/O is possible
269 Fcb
->NTRequiredFCB
->CommonFCBHeader
.IsFastIoPossible
= UDFIsFastIoPossible(Fcb
);
275 // Release the Fcb, and return to our caller
278 // UDFReleaseResource( (Fcb)->Header.Resource );
280 FsRtlExitFileSystem();
285 } // end UDFFastLock()
291 This is a call back routine for doing the fast unlock single call.
295 FileObject - Supplies the file object used in this operation
296 FileOffset - Supplies the file offset used in this operation
297 Length - Supplies the length used in this operation
298 ProcessId - Supplies the process ID used in this operation
299 Key - Supplies the key used in this operation
300 Status - Receives the Status if this operation is successful
304 BOOLEAN - TRUE if this operation completed and FALSE if caller
305 needs to take the long route.
310 IN PFILE_OBJECT FileObject
,
311 IN PLARGE_INTEGER FileOffset
,
312 IN PLARGE_INTEGER Length
,
315 OUT PIO_STATUS_BLOCK IoStatus
,
316 IN PDEVICE_OBJECT DeviceObject
320 BOOLEAN Results
= FALSE
;
322 // BOOLEAN AcquiredFCB = FALSE;
323 PtrUDFFCB Fcb
= NULL
;
324 PtrUDFCCB Ccb
= NULL
;
326 UDFPrint(("UDFFastUnlockSingle\n"));
327 // Decode the type of file object we're being asked to process and make
328 // sure it is only a user file open.
330 IoStatus
->Information
= 0;
332 // Get the FCB and CCB pointers.
333 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
337 // Validate the sent-in FCB
338 if ( (Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
339 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
341 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
345 // Acquire exclusive access to the Fcb this operation can always wait
347 FsRtlEnterFileSystem();
350 // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE );
354 // We check whether we can proceed
355 // based on the state of the file oplocks.
357 // Now call the FsRtl routine to do the actual processing of the
360 IoStatus
->Status
= FsRtlFastUnlockSingle( &(Fcb
->NTRequiredFCB
->FileLock
),
368 // Set the flag indicating if Fast I/O is possible
369 Fcb
->NTRequiredFCB
->CommonFCBHeader
.IsFastIoPossible
= UDFIsFastIoPossible(Fcb
);
374 // Release the Fcb, and return to our caller
377 // UDFReleaseResource( (Fcb)->Header.Resource );
379 FsRtlExitFileSystem();
384 } // end UDFFastUnlockSingle()
390 This is a call back routine for doing the fast unlock all call.
393 FileObject - Supplies the file object used in this operation
394 ProcessId - Supplies the process ID used in this operation
395 Status - Receives the Status if this operation is successful
399 BOOLEAN - TRUE if this operation completed and FALSE if caller
400 needs to take the long route.
405 IN PFILE_OBJECT FileObject
,
407 OUT PIO_STATUS_BLOCK IoStatus
,
408 IN PDEVICE_OBJECT DeviceObject
412 BOOLEAN Results
= FALSE
;
414 // BOOLEAN AcquiredFCB = FALSE;
415 PtrUDFFCB Fcb
= NULL
;
416 PtrUDFCCB Ccb
= NULL
;
418 UDFPrint(("UDFFastUnlockAll\n"));
420 IoStatus
->Information
= 0;
421 // Decode the type of file object we're being asked to process and make
422 // sure it is only a user file open.
424 // Get the FCB and CCB pointers.
425 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
429 // Validate the sent-in FCB
430 if ( (Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
431 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
433 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
437 // Acquire shared access to the Fcb this operation can always wait
439 FsRtlEnterFileSystem();
441 UDF_CHECK_PAGING_IO_RESOURCE(Fcb
->NTRequiredFCB
);
442 UDFAcquireResourceShared( &(Fcb
->NTRequiredFCB
->MainResource
),TRUE
);
446 // We check whether we can proceed
447 // based on the state of the file oplocks.
449 // Now call the FsRtl routine to do the actual processing of the
452 IoStatus
->Status
= FsRtlFastUnlockAll( &(Fcb
->NTRequiredFCB
->FileLock
),
457 // Set the flag indicating if Fast I/O is questionable
459 Fcb
->NTRequiredFCB
->CommonFCBHeader
.IsFastIoPossible
= UDFIsFastIoPossible( Fcb
);
464 // Release the Fcb, and return to our caller
466 UDF_CHECK_PAGING_IO_RESOURCE(Fcb
->NTRequiredFCB
);
467 UDFReleaseResource(&(Fcb
->NTRequiredFCB
->MainResource
));
468 FsRtlExitFileSystem();
473 } // end UDFFastUnlockAll()
479 This is a call back routine for doing the fast unlock all call.
482 FileObject - Supplies the file object used in this operation
483 ProcessId - Supplies the process ID used in this operation
484 Status - Receives the Status if this operation is successful
488 BOOLEAN - TRUE if this operation completed and FALSE if caller
489 needs to take the long route.
494 UDFFastUnlockAllByKey(
495 IN PFILE_OBJECT FileObject
,
498 OUT PIO_STATUS_BLOCK IoStatus
,
499 IN PDEVICE_OBJECT DeviceObject
503 BOOLEAN Results
= FALSE
;
505 // BOOLEAN AcquiredFCB = FALSE;
506 PtrUDFFCB Fcb
= NULL
;
507 PtrUDFCCB Ccb
= NULL
;
509 UDFPrint(("UDFFastUnlockAllByKey\n"));
511 IoStatus
->Information
= 0;
512 // Decode the type of file object we're being asked to process and make
513 // sure it is only a user file open.
515 // Get the FCB and CCB pointers.
516 Ccb
= (PtrUDFCCB
)(FileObject
->FsContext2
);
520 // Validate the sent-in FCB
521 if ( (Fcb
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_VCB
) ||
522 (Fcb
->FCBFlags
& UDF_FCB_DIRECTORY
)) {
524 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
528 // Acquire shared access to the Fcb this operation can always wait
530 FsRtlEnterFileSystem();
532 UDF_CHECK_PAGING_IO_RESOURCE(Fcb
->NTRequiredFCB
);
533 UDFAcquireResourceShared( &(Fcb
->NTRequiredFCB
->MainResource
),TRUE
);
537 // We check whether we can proceed
538 // based on the state of the file oplocks.
540 // Now call the FsRtl routine to do the actual processing of the
543 IoStatus
->Status
= FsRtlFastUnlockAllByKey( &(Fcb
->NTRequiredFCB
->FileLock
),
549 // Set the flag indicating if Fast I/O is possible
551 Fcb
->NTRequiredFCB
->CommonFCBHeader
.IsFastIoPossible
= UDFIsFastIoPossible( Fcb
);
556 // Release the Fcb, and return to our caller
558 UDF_CHECK_PAGING_IO_RESOURCE(Fcb
->NTRequiredFCB
);
559 UDFReleaseResource(&(Fcb
->NTRequiredFCB
->MainResource
));
560 FsRtlExitFileSystem();
565 } // end UDFFastUnlockAllByKey()