1 /*++ 2 3 Copyright (c) 1989-2000 Microsoft Corporation 4 5 Module Name: 6 7 LockCtrl.c 8 9 Abstract: 10 11 This module implements the Lock Control routines for Cdfs called 12 by the Fsd/Fsp dispatch driver. 13 14 15 --*/ 16 17 #include "cdprocs.h" 18 19 // 20 // The Bug check file id for this module 21 // 22 23 #define BugCheckFileId (CDFS_BUG_CHECK_LOCKCTRL) 24 25 #ifdef ALLOC_PRAGMA 26 #pragma alloc_text(PAGE, CdCommonLockControl) 27 #pragma alloc_text(PAGE, CdFastLock) 28 #pragma alloc_text(PAGE, CdFastUnlockAll) 29 #pragma alloc_text(PAGE, CdFastUnlockAllByKey) 30 #pragma alloc_text(PAGE, CdFastUnlockSingle) 31 #endif 32 33 34 NTSTATUS 35 CdCommonLockControl ( 36 _Inout_ PIRP_CONTEXT IrpContext, 37 _Inout_ PIRP Irp 38 ) 39 40 /*++ 41 42 Routine Description: 43 44 This is the common routine for Lock Control called by both the fsd and fsp 45 threads. 46 47 Arguments: 48 49 Irp - Supplies the Irp to process 50 51 Return Value: 52 53 NTSTATUS - The return status for the operation 54 55 --*/ 56 57 { 58 NTSTATUS Status; 59 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 60 61 TYPE_OF_OPEN TypeOfOpen; 62 PFCB Fcb; 63 PCCB Ccb; 64 65 PAGED_CODE(); 66 67 // 68 // Extract and decode the type of file object we're being asked to process 69 // 70 71 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); 72 73 // 74 // If the file is not a user file open then we reject the request 75 // as an invalid parameter 76 // 77 78 if (TypeOfOpen != UserFileOpen) { 79 80 CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); 81 return STATUS_INVALID_PARAMETER; 82 } 83 84 // 85 // We check whether we can proceed based on the state of the file oplocks. 86 // This call might post the irp for us. 87 // 88 89 Status = FsRtlCheckOplock( CdGetFcbOplock(Fcb), 90 Irp, 91 IrpContext, 92 (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */ 93 NULL ); 94 95 // 96 // If we don't get success then the oplock package completed the request. 97 // 98 99 if (Status != STATUS_SUCCESS) { 100 101 return Status; 102 } 103 104 // 105 // Verify the Fcb. 106 // 107 108 CdVerifyFcbOperation( IrpContext, Fcb ); 109 110 // 111 // If we don't have a file lock, then get one now. 112 // 113 114 if (Fcb->FileLock == NULL) { CdCreateFileLock( IrpContext, Fcb, TRUE ); } 115 116 // 117 // Now call the FsRtl routine to do the actual processing of the 118 // Lock request 119 // 120 121 Status = FsRtlProcessFileLock( Fcb->FileLock, Irp, NULL ); 122 123 // 124 // Set the flag indicating if Fast I/O is possible 125 // 126 127 CdLockFcb( IrpContext, Fcb ); 128 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); 129 CdUnlockFcb( IrpContext, Fcb ); 130 131 // 132 // Complete the request. 133 // 134 135 CdCompleteRequest( IrpContext, NULL, Status ); 136 return Status; 137 } 138 139 140 BOOLEAN 141 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 142 CdFastLock ( 143 _In_ PFILE_OBJECT FileObject, 144 _In_ PLARGE_INTEGER FileOffset, 145 _In_ PLARGE_INTEGER Length, 146 _In_ PEPROCESS ProcessId, 147 _In_ ULONG Key, 148 _In_ BOOLEAN FailImmediately, 149 _In_ BOOLEAN ExclusiveLock, 150 _Out_ PIO_STATUS_BLOCK IoStatus, 151 _In_ PDEVICE_OBJECT DeviceObject 152 ) 153 154 /*++ 155 156 Routine Description: 157 158 This is a call back routine for doing the fast lock call. 159 160 Arguments: 161 162 FileObject - Supplies the file object used in this operation 163 164 FileOffset - Supplies the file offset used in this operation 165 166 Length - Supplies the length used in this operation 167 168 ProcessId - Supplies the process ID used in this operation 169 170 Key - Supplies the key used in this operation 171 172 FailImmediately - Indicates if the request should fail immediately 173 if the lock cannot be granted. 174 175 ExclusiveLock - Indicates if this is a request for an exclusive or 176 shared lock 177 178 IoStatus - Receives the Status if this operation is successful 179 180 Return Value: 181 182 BOOLEAN - TRUE if this operation completed and FALSE if caller 183 needs to take the long route. 184 185 --*/ 186 187 { 188 BOOLEAN Results = FALSE; 189 190 PFCB Fcb; 191 TYPE_OF_OPEN TypeOfOpen; 192 193 PAGED_CODE(); 194 195 UNREFERENCED_PARAMETER( DeviceObject ); 196 197 ASSERT_FILE_OBJECT( FileObject ); 198 199 IoStatus->Information = 0; 200 201 // 202 // Decode the type of file object we're being asked to process and 203 // make sure that is is only a user file open. 204 // 205 206 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 207 208 if (TypeOfOpen != UserFileOpen) { 209 210 IoStatus->Status = STATUS_INVALID_PARAMETER; 211 return TRUE; 212 } 213 214 // 215 // Only deal with 'good' Fcb's. 216 // 217 218 if (!CdVerifyFcbOperation( NULL, Fcb )) { 219 220 return FALSE; 221 } 222 223 FsRtlEnterFileSystem(); 224 225 // 226 // Use a try-finally to facilitate cleanup. 227 // 228 229 _SEH2_TRY { 230 231 // 232 // We check whether we can proceed based on the state of the file oplocks. 233 // 234 235 if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 236 237 try_return( NOTHING ); 238 } 239 240 // 241 // If we don't have a file lock, then get one now. 242 // 243 244 if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) { 245 246 try_return( NOTHING ); 247 } 248 249 // 250 // Now call the FsRtl routine to perform the lock request. 251 // 252 253 #ifdef _MSC_VER 254 #pragma prefast(suppress: 28159, "prefast thinks this is an obsolete routine, but it is ok for CDFS to use it") 255 #endif 256 if ((Results = FsRtlFastLock( Fcb->FileLock, 257 FileObject, 258 FileOffset, 259 Length, 260 ProcessId, 261 Key, 262 FailImmediately, 263 ExclusiveLock, 264 IoStatus, 265 NULL, 266 FALSE )) != FALSE) { 267 268 // 269 // Set the flag indicating if Fast I/O is questionable. We 270 // only change this flag if the current state is possible. 271 // Retest again after synchronizing on the header. 272 // 273 274 if (Fcb->IsFastIoPossible == FastIoIsPossible) { 275 276 CdLockFcb( NULL, Fcb ); 277 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); 278 CdUnlockFcb( NULL, Fcb ); 279 } 280 } 281 282 try_exit: NOTHING; 283 } _SEH2_FINALLY { 284 285 FsRtlExitFileSystem(); 286 } _SEH2_END; 287 288 return Results; 289 } 290 291 292 BOOLEAN 293 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 294 CdFastUnlockSingle ( 295 _In_ PFILE_OBJECT FileObject, 296 _In_ PLARGE_INTEGER FileOffset, 297 _In_ PLARGE_INTEGER Length, 298 _In_ PEPROCESS ProcessId, 299 _In_ ULONG Key, 300 _Out_ PIO_STATUS_BLOCK IoStatus, 301 _In_ PDEVICE_OBJECT DeviceObject 302 ) 303 304 /*++ 305 306 Routine Description: 307 308 This is a call back routine for doing the fast unlock single call. 309 310 Arguments: 311 312 FileObject - Supplies the file object used in this operation 313 314 FileOffset - Supplies the file offset used in this operation 315 316 Length - Supplies the length used in this operation 317 318 ProcessId - Supplies the process ID used in this operation 319 320 Key - Supplies the key used in this operation 321 322 Status - Receives the Status if this operation is successful 323 324 Return Value: 325 326 BOOLEAN - TRUE if this operation completed and FALSE if caller 327 needs to take the long route. 328 329 --*/ 330 331 { 332 BOOLEAN Results = FALSE; 333 TYPE_OF_OPEN TypeOfOpen; 334 PFCB Fcb; 335 336 PAGED_CODE(); 337 338 UNREFERENCED_PARAMETER( DeviceObject ); 339 340 IoStatus->Information = 0; 341 342 // 343 // Decode the type of file object we're being asked to process and 344 // make sure that is is only a user file open. 345 // 346 347 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 348 349 if (TypeOfOpen != UserFileOpen) { 350 351 IoStatus->Status = STATUS_INVALID_PARAMETER; 352 return TRUE; 353 } 354 355 // 356 // Only deal with 'good' Fcb's. 357 // 358 359 if (!CdVerifyFcbOperation( NULL, Fcb )) { 360 361 return FALSE; 362 } 363 364 // 365 // If there is no lock then return immediately. 366 // 367 368 if (Fcb->FileLock == NULL) { 369 370 IoStatus->Status = STATUS_RANGE_NOT_LOCKED; 371 return TRUE; 372 } 373 374 FsRtlEnterFileSystem(); 375 376 _SEH2_TRY { 377 378 // 379 // We check whether we can proceed based on the state of the file oplocks. 380 // 381 382 if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 383 384 try_return( NOTHING ); 385 } 386 387 // 388 // If we don't have a file lock, then get one now. 389 // 390 391 if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) { 392 393 try_return( NOTHING ); 394 } 395 396 // 397 // Now call the FsRtl routine to do the actual processing of the 398 // Lock request. The call will always succeed. 399 // 400 401 Results = TRUE; 402 IoStatus->Status = FsRtlFastUnlockSingle( Fcb->FileLock, 403 FileObject, 404 FileOffset, 405 Length, 406 ProcessId, 407 Key, 408 NULL, 409 FALSE ); 410 411 // 412 // Set the flag indicating if Fast I/O is possible. We are 413 // only concerned if there are no longer any filelocks on this 414 // file. 415 // 416 417 if (!FsRtlAreThereCurrentFileLocks( Fcb->FileLock ) && 418 (Fcb->IsFastIoPossible != FastIoIsPossible)) { 419 420 CdLockFcb( IrpContext, Fcb ); 421 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); 422 CdUnlockFcb( IrpContext, Fcb ); 423 } 424 425 try_exit: NOTHING; 426 } _SEH2_FINALLY { 427 428 FsRtlExitFileSystem(); 429 } _SEH2_END; 430 431 return Results; 432 } 433 434 435 BOOLEAN 436 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 437 CdFastUnlockAll ( 438 _In_ PFILE_OBJECT FileObject, 439 _In_ PEPROCESS ProcessId, 440 _Out_ PIO_STATUS_BLOCK IoStatus, 441 _In_ PDEVICE_OBJECT DeviceObject 442 ) 443 444 /*++ 445 446 Routine Description: 447 448 This is a call back routine for doing the fast unlock all call. 449 450 Arguments: 451 452 FileObject - Supplies the file object used in this operation 453 454 ProcessId - Supplies the process ID used in this operation 455 456 Status - Receives the Status if this operation is successful 457 458 Return Value: 459 460 BOOLEAN - TRUE if this operation completed and FALSE if caller 461 needs to take the long route. 462 463 --*/ 464 465 { 466 BOOLEAN Results = FALSE; 467 TYPE_OF_OPEN TypeOfOpen; 468 PFCB Fcb; 469 470 PAGED_CODE(); 471 472 UNREFERENCED_PARAMETER( DeviceObject ); 473 474 IoStatus->Information = 0; 475 476 // 477 // Decode the type of file object we're being asked to process and 478 // make sure that is is only a user file open. 479 // 480 481 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 482 483 if (TypeOfOpen != UserFileOpen) { 484 485 IoStatus->Status = STATUS_INVALID_PARAMETER; 486 return TRUE; 487 } 488 489 // 490 // Only deal with 'good' Fcb's. 491 // 492 493 if (!CdVerifyFcbOperation( NULL, Fcb )) { 494 495 return FALSE; 496 } 497 498 // 499 // If there is no lock then return immediately. 500 // 501 502 if (Fcb->FileLock == NULL) { 503 504 IoStatus->Status = STATUS_RANGE_NOT_LOCKED; 505 return TRUE; 506 } 507 508 FsRtlEnterFileSystem(); 509 510 _SEH2_TRY { 511 512 // 513 // We check whether we can proceed based on the state of the file oplocks. 514 // 515 516 if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 517 518 try_return( NOTHING ); 519 } 520 521 // 522 // If we don't have a file lock, then get one now. 523 // 524 525 if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) { 526 527 try_return( NOTHING ); 528 } 529 530 // 531 // Now call the FsRtl routine to do the actual processing of the 532 // Lock request. The call will always succeed. 533 // 534 535 Results = TRUE; 536 IoStatus->Status = FsRtlFastUnlockAll( Fcb->FileLock, 537 FileObject, 538 ProcessId, 539 NULL ); 540 541 542 // 543 // Set the flag indicating if Fast I/O is possible 544 // 545 546 CdLockFcb( IrpContext, Fcb ); 547 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); 548 CdUnlockFcb( IrpContext, Fcb ); 549 550 try_exit: NOTHING; 551 } _SEH2_FINALLY { 552 553 FsRtlExitFileSystem(); 554 } _SEH2_END; 555 556 return Results; 557 } 558 559 560 BOOLEAN 561 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ 562 CdFastUnlockAllByKey ( 563 _In_ PFILE_OBJECT FileObject, 564 _In_ PVOID ProcessId, 565 _In_ ULONG Key, 566 _Out_ PIO_STATUS_BLOCK IoStatus, 567 _In_ PDEVICE_OBJECT DeviceObject 568 ) 569 570 /*++ 571 572 Routine Description: 573 574 This is a call back routine for doing the fast unlock all by key call. 575 576 Arguments: 577 578 FileObject - Supplies the file object used in this operation 579 580 ProcessId - Supplies the process ID used in this operation 581 582 Key - Supplies the key used in this operation 583 584 Status - Receives the Status if this operation is successful 585 586 Return Value: 587 588 BOOLEAN - TRUE if this operation completed and FALSE if caller 589 needs to take the long route. 590 591 --*/ 592 593 { 594 BOOLEAN Results = FALSE; 595 TYPE_OF_OPEN TypeOfOpen; 596 PFCB Fcb; 597 598 PAGED_CODE(); 599 600 UNREFERENCED_PARAMETER( DeviceObject ); 601 602 IoStatus->Information = 0; 603 604 // 605 // Decode the type of file object we're being asked to process and 606 // make sure that is is only a user file open. 607 // 608 609 TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); 610 611 if (TypeOfOpen != UserFileOpen) { 612 613 IoStatus->Status = STATUS_INVALID_PARAMETER; 614 return TRUE; 615 } 616 617 // 618 // Only deal with 'good' Fcb's. 619 // 620 621 if (!CdVerifyFcbOperation( NULL, Fcb )) { 622 623 return FALSE; 624 } 625 626 // 627 // If there is no lock then return immediately. 628 // 629 630 if (Fcb->FileLock == NULL) { 631 632 IoStatus->Status = STATUS_RANGE_NOT_LOCKED; 633 return TRUE; 634 } 635 636 FsRtlEnterFileSystem(); 637 638 _SEH2_TRY { 639 640 // 641 // We check whether we can proceed based on the state of the file oplocks. 642 // 643 644 if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 645 646 try_return( NOTHING ); 647 } 648 649 // 650 // If we don't have a file lock, then get one now. 651 // 652 653 if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) { 654 655 try_return( NOTHING ); 656 } 657 658 // 659 // Now call the FsRtl routine to do the actual processing of the 660 // Lock request. The call will always succeed. 661 // 662 663 Results = TRUE; 664 IoStatus->Status = FsRtlFastUnlockAllByKey( Fcb->FileLock, 665 FileObject, 666 ProcessId, 667 Key, 668 NULL ); 669 670 671 // 672 // Set the flag indicating if Fast I/O is possible 673 // 674 675 CdLockFcb( IrpContext, Fcb ); 676 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); 677 CdUnlockFcb( IrpContext, Fcb ); 678 679 try_exit: NOTHING; 680 } _SEH2_FINALLY { 681 682 FsRtlExitFileSystem(); 683 } _SEH2_END; 684 685 return Results; 686 } 687 688 689 690