Reactos
at master 565 lines 17 kB view raw
1//////////////////////////////////////////////////////////////////// 2// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3// All rights reserved 4// This file was released under the GPLv2 on June 2015. 5//////////////////////////////////////////////////////////////////// 6/************************************************************************* 7* 8* File: LockCtrl.cpp.cpp 9* 10* Module: UDF File System Driver (Kernel mode execution only) 11* 12* Description: 13* Contains code to handle the "byte-range locking" dispatch entry point. 14* 15*************************************************************************/ 16 17#include "udffs.h" 18 19// define the file specific bug-check id 20#define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN 21 22 23/************************************************************************* 24* 25* Function: UDFLockControl() 26* 27* Description: 28* 29* Expected Interrupt Level (for execution) : 30* 31* IRQL_PASSIVE_LEVEL 32* 33* Return Value: Irrelevant. 34* 35*************************************************************************/ 36NTSTATUS 37NTAPI 38UDFLockControl( 39 IN PDEVICE_OBJECT DeviceObject, // the logical volume device object 40 IN PIRP Irp) // I/O Request Packet 41{ 42 NTSTATUS RC = STATUS_SUCCESS; 43 PtrUDFIrpContext PtrIrpContext = NULL; 44 BOOLEAN AreWeTopLevel = FALSE; 45 46 UDFPrint(("UDFLockControl\n")); 47// BrutePoint(); 48 49 FsRtlEnterFileSystem(); 50 ASSERT(DeviceObject); 51 ASSERT(Irp); 52 53 // set the top level context 54 AreWeTopLevel = UDFIsIrpTopLevel(Irp); 55 // Call the common Lock Control routine, with blocking allowed if 56 // synchronous 57 _SEH2_TRY { 58 59 // get an IRP context structure and issue the request 60 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); 61 if(PtrIrpContext) { 62 RC = UDFCommonLockControl(PtrIrpContext, Irp); 63 } else { 64 RC = STATUS_INSUFFICIENT_RESOURCES; 65 Irp->IoStatus.Status = RC; 66 Irp->IoStatus.Information = 0; 67 // complete the IRP 68 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 69 } 70 71 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) { 72 73 RC = UDFExceptionHandler(PtrIrpContext, Irp); 74 75 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); 76 } _SEH2_END; 77 78 if (AreWeTopLevel) { 79 IoSetTopLevelIrp(NULL); 80 } 81 82 FsRtlExitFileSystem(); 83 84 return(RC); 85} // end UDFLockControl() 86 87 88/************************************************************************* 89* 90* Function: UDFCommonLockControl() 91* 92* Description: 93* This is the common routine for doing Lock control operations called 94* by both the fsd and fsp threads 95* 96* Expected Interrupt Level (for execution) : 97* 98* IRQL_PASSIVE_LEVEL 99* 100* Return Value: Irrelevant 101* 102*************************************************************************/ 103NTSTATUS 104NTAPI 105UDFCommonLockControl( 106 IN PtrUDFIrpContext PtrIrpContext, 107 IN PIRP Irp) 108{ 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; 120 121 UDFPrint(("UDFCommonLockControl\n")); 122 123 _SEH2_TRY { 124 // First, get a pointer to the current I/O stack location. 125 IrpSp = IoGetCurrentIrpStackLocation(Irp); 126 ASSERT(IrpSp); 127 128 FileObject = IrpSp->FileObject; 129 ASSERT(FileObject); 130 131 // Get the FCB and CCB pointers. 132 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 133 ASSERT(Ccb); 134 Fcb = Ccb->Fcb; 135 ASSERT(Fcb); 136 // Validate the sent-in FCB 137 if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || 138 (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { 139 140// CompleteRequest = TRUE; 141 try_return(RC = STATUS_INVALID_PARAMETER); 142 } 143 144 NtReqFcb = Fcb->NTRequiredFCB; 145 CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 146 147 // Acquire the FCB resource shared 148 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 149 if (!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) { 150 PostRequest = TRUE; 151 try_return(RC = STATUS_PENDING); 152 } 153 AcquiredFCB = TRUE; 154 155 RC = FsRtlProcessFileLock(&(NtReqFcb->FileLock), Irp, NULL); 156// CompleteRequest = TRUE; 157 158try_exit: NOTHING; 159 160 } _SEH2_FINALLY { 161 162 // Release the FCB resources if acquired. 163 if (AcquiredFCB) { 164 UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); 165 UDFReleaseResource(&(NtReqFcb->MainResource)); 166 AcquiredFCB = FALSE; 167 } 168 if (PostRequest) { 169 // Perform appropriate post related processing here 170 RC = UDFPostRequest(PtrIrpContext, Irp); 171 } else 172 if(!_SEH2_AbnormalTermination()) { 173 // Simply free up the IrpContext since the IRP has been queued or 174 // Completed by FsRtlProcessFileLock 175 UDFReleaseIrpContext(PtrIrpContext); 176 } 177 } _SEH2_END; // end of "__finally" processing 178 179 return(RC); 180} // end UDFCommonLockControl() 181 182 183/* 184Routine Description: 185 This is a call back routine for doing the fast lock call. 186Arguments: 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 195 shared lock 196 IoStatus - Receives the Status if this operation is successful 197 198Return Value: 199 BOOLEAN - TRUE if this operation completed and FALSE if caller 200 needs to take the long route. 201*/ 202 203BOOLEAN 204NTAPI 205UDFFastLock ( 206 IN PFILE_OBJECT FileObject, 207 IN PLARGE_INTEGER FileOffset, 208 IN PLARGE_INTEGER Length, 209 PEPROCESS ProcessId, 210 ULONG Key, 211 BOOLEAN FailImmediately, 212 BOOLEAN ExclusiveLock, 213 OUT PIO_STATUS_BLOCK IoStatus, 214 IN PDEVICE_OBJECT DeviceObject 215 ) 216{ 217 BOOLEAN Results = FALSE; 218 219// BOOLEAN AcquiredFCB = FALSE; 220 PtrUDFFCB Fcb = NULL; 221 PtrUDFCCB Ccb = NULL; 222 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. 226 227 228 // Get the FCB and CCB pointers. 229 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 230 ASSERT(Ccb); 231 Fcb = Ccb->Fcb; 232 ASSERT(Fcb); 233 // Validate the sent-in FCB 234 if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || 235 (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { 236 237 IoStatus->Status = STATUS_INVALID_PARAMETER; 238 IoStatus->Information = 0; 239 return TRUE; 240 } 241 242 // Acquire exclusive access to the Fcb this operation can always wait 243 244 FsRtlEnterFileSystem(); 245 246 // BUGBUG: kenr 247 // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); 248 249 _SEH2_TRY { 250 251 // We check whether we can proceed 252 // based on the state of the file oplocks. 253 254 // Now call the FsRtl routine to do the actual processing of the 255 // Lock request 256 if ((Results = FsRtlFastLock( &(Fcb->NTRequiredFCB->FileLock), 257 FileObject, 258 FileOffset, 259 Length, 260 ProcessId, 261 Key, 262 FailImmediately, 263 ExclusiveLock, 264 IoStatus, 265 NULL, 266 FALSE ))) { 267 268 // Set the flag indicating if Fast I/O is possible 269 Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb); 270 } 271 272//try_exit: NOTHING; 273 } _SEH2_FINALLY { 274 275 // Release the Fcb, and return to our caller 276 277 // BUGBUG: kenr 278 // UDFReleaseResource( (Fcb)->Header.Resource ); 279 280 FsRtlExitFileSystem(); 281 282 } _SEH2_END; 283 284 return Results; 285} // end UDFFastLock() 286 287 288/* 289Routine Description: 290 291 This is a call back routine for doing the fast unlock single call. 292 293Arguments: 294 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 301 302Return Value: 303 304 BOOLEAN - TRUE if this operation completed and FALSE if caller 305 needs to take the long route. 306*/ 307BOOLEAN 308NTAPI 309UDFFastUnlockSingle( 310 IN PFILE_OBJECT FileObject, 311 IN PLARGE_INTEGER FileOffset, 312 IN PLARGE_INTEGER Length, 313 PEPROCESS ProcessId, 314 ULONG Key, 315 OUT PIO_STATUS_BLOCK IoStatus, 316 IN PDEVICE_OBJECT DeviceObject 317 ) 318 319{ 320 BOOLEAN Results = FALSE; 321 322// BOOLEAN AcquiredFCB = FALSE; 323 PtrUDFFCB Fcb = NULL; 324 PtrUDFCCB Ccb = NULL; 325 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. 329 330 IoStatus->Information = 0; 331 332 // Get the FCB and CCB pointers. 333 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 334 ASSERT(Ccb); 335 Fcb = Ccb->Fcb; 336 ASSERT(Fcb); 337 // Validate the sent-in FCB 338 if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || 339 (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { 340 341 IoStatus->Status = STATUS_INVALID_PARAMETER; 342 return TRUE; 343 } 344 345 // Acquire exclusive access to the Fcb this operation can always wait 346 347 FsRtlEnterFileSystem(); 348 349 // BUGBUG: kenr 350 // (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE ); 351 352 _SEH2_TRY { 353 354 // We check whether we can proceed 355 // based on the state of the file oplocks. 356 357 // Now call the FsRtl routine to do the actual processing of the 358 // Lock request 359 Results = TRUE; 360 IoStatus->Status = FsRtlFastUnlockSingle( &(Fcb->NTRequiredFCB->FileLock), 361 FileObject, 362 FileOffset, 363 Length, 364 ProcessId, 365 Key, 366 NULL, 367 FALSE ); 368 // Set the flag indicating if Fast I/O is possible 369 Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb); 370 371//try_exit: NOTHING; 372 } _SEH2_FINALLY { 373 374 // Release the Fcb, and return to our caller 375 376 // BUGBUG: kenr 377 // UDFReleaseResource( (Fcb)->Header.Resource ); 378 379 FsRtlExitFileSystem(); 380 381 } _SEH2_END; 382 383 return Results; 384} // end UDFFastUnlockSingle() 385 386 387/* 388Routine Description: 389 390 This is a call back routine for doing the fast unlock all call. 391 392Arguments: 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 396 397Return Value: 398 399 BOOLEAN - TRUE if this operation completed and FALSE if caller 400 needs to take the long route. 401*/ 402BOOLEAN 403NTAPI 404UDFFastUnlockAll( 405 IN PFILE_OBJECT FileObject, 406 PEPROCESS ProcessId, 407 OUT PIO_STATUS_BLOCK IoStatus, 408 IN PDEVICE_OBJECT DeviceObject 409 ) 410 411{ 412 BOOLEAN Results = FALSE; 413 414// BOOLEAN AcquiredFCB = FALSE; 415 PtrUDFFCB Fcb = NULL; 416 PtrUDFCCB Ccb = NULL; 417 418 UDFPrint(("UDFFastUnlockAll\n")); 419 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. 423 424 // Get the FCB and CCB pointers. 425 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 426 ASSERT(Ccb); 427 Fcb = Ccb->Fcb; 428 ASSERT(Fcb); 429 // Validate the sent-in FCB 430 if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || 431 (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { 432 433 IoStatus->Status = STATUS_INVALID_PARAMETER; 434 return TRUE; 435 } 436 437 // Acquire shared access to the Fcb this operation can always wait 438 439 FsRtlEnterFileSystem(); 440 441 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB); 442 UDFAcquireResourceShared( &(Fcb->NTRequiredFCB->MainResource),TRUE ); 443 444 _SEH2_TRY { 445 446 // We check whether we can proceed 447 // based on the state of the file oplocks. 448 449 // Now call the FsRtl routine to do the actual processing of the 450 // Lock request 451 Results = TRUE; 452 IoStatus->Status = FsRtlFastUnlockAll( &(Fcb->NTRequiredFCB->FileLock), 453 FileObject, 454 ProcessId, 455 NULL ); 456 457 // Set the flag indicating if Fast I/O is questionable 458 459 Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible( Fcb ); 460 461//try_exit: NOTHING; 462 } _SEH2_FINALLY { 463 464 // Release the Fcb, and return to our caller 465 466 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB); 467 UDFReleaseResource(&(Fcb->NTRequiredFCB->MainResource)); 468 FsRtlExitFileSystem(); 469 470 } _SEH2_END; 471 472 return Results; 473} // end UDFFastUnlockAll() 474 475 476/* 477Routine Description: 478 479 This is a call back routine for doing the fast unlock all call. 480 481Arguments: 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 485 486Return Value: 487 488 BOOLEAN - TRUE if this operation completed and FALSE if caller 489 needs to take the long route. 490*/ 491 492BOOLEAN 493NTAPI 494UDFFastUnlockAllByKey( 495 IN PFILE_OBJECT FileObject, 496 PEPROCESS ProcessId, 497 ULONG Key, 498 OUT PIO_STATUS_BLOCK IoStatus, 499 IN PDEVICE_OBJECT DeviceObject 500 ) 501 502{ 503 BOOLEAN Results = FALSE; 504 505// BOOLEAN AcquiredFCB = FALSE; 506 PtrUDFFCB Fcb = NULL; 507 PtrUDFCCB Ccb = NULL; 508 509 UDFPrint(("UDFFastUnlockAllByKey\n")); 510 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. 514 515 // Get the FCB and CCB pointers. 516 Ccb = (PtrUDFCCB)(FileObject->FsContext2); 517 ASSERT(Ccb); 518 Fcb = Ccb->Fcb; 519 ASSERT(Fcb); 520 // Validate the sent-in FCB 521 if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || 522 (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { 523 524 IoStatus->Status = STATUS_INVALID_PARAMETER; 525 return TRUE; 526 } 527 528 // Acquire shared access to the Fcb this operation can always wait 529 530 FsRtlEnterFileSystem(); 531 532 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB); 533 UDFAcquireResourceShared( &(Fcb->NTRequiredFCB->MainResource),TRUE ); 534 535 _SEH2_TRY { 536 537 // We check whether we can proceed 538 // based on the state of the file oplocks. 539 540 // Now call the FsRtl routine to do the actual processing of the 541 // Lock request 542 Results = TRUE; 543 IoStatus->Status = FsRtlFastUnlockAllByKey( &(Fcb->NTRequiredFCB->FileLock), 544 FileObject, 545 ProcessId, 546 Key, 547 NULL ); 548 549 // Set the flag indicating if Fast I/O is possible 550 551 Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible( Fcb ); 552 553//try_exit: NOTHING; 554 } _SEH2_FINALLY { 555 556 // Release the Fcb, and return to our caller 557 558 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB); 559 UDFReleaseResource(&(Fcb->NTRequiredFCB->MainResource)); 560 FsRtlExitFileSystem(); 561 562 } _SEH2_END; 563 564 return Results; 565} // end UDFFastUnlockAllByKey()