Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

904 lines
22 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. LockCtrl.c
  5. Abstract:
  6. This module implements the File Lock Control routine for Ntfs called by the
  7. dispatch driver.
  8. Author:
  9. Gary Kimura [GaryKi] 28-May-1991
  10. Revision History:
  11. --*/
  12. #include "NtfsProc.h"
  13. //
  14. // The local debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_LOCKCTRL)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, NtfsCommonLockControl)
  19. #pragma alloc_text(PAGE, NtfsFastLock)
  20. #pragma alloc_text(PAGE, NtfsFastUnlockAll)
  21. #pragma alloc_text(PAGE, NtfsFastUnlockAllByKey)
  22. #pragma alloc_text(PAGE, NtfsFastUnlockSingle)
  23. #endif
  24. NTSTATUS
  25. NtfsFsdLockControl (
  26. IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
  27. IN PIRP Irp
  28. )
  29. /*++
  30. Routine Description:
  31. This routine implements the FSD part of Lock Control.
  32. Arguments:
  33. VolumeDeviceObject - Supplies the volume device object where the
  34. file exists
  35. Irp - Supplies the Irp being processed
  36. Return Value:
  37. NTSTATUS - The FSD status for the IRP
  38. --*/
  39. {
  40. TOP_LEVEL_CONTEXT TopLevelContext;
  41. PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
  42. NTSTATUS Status = STATUS_SUCCESS;
  43. PIRP_CONTEXT IrpContext = NULL;
  44. ASSERT_IRP( Irp );
  45. UNREFERENCED_PARAMETER( VolumeDeviceObject );
  46. DebugTrace( +1, Dbg, ("NtfsFsdLockControl\n") );
  47. //
  48. // Call the common Lock Control routine
  49. //
  50. FsRtlEnterFileSystem();
  51. ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, FALSE, FALSE );
  52. do {
  53. try {
  54. //
  55. // We are either initiating this request or retrying it.
  56. //
  57. if (IrpContext == NULL) {
  58. //
  59. // Allocate and initialize the Irp.
  60. //
  61. NtfsInitializeIrpContext( Irp, CanFsdWait( Irp ), &IrpContext );
  62. //
  63. // Initialize the thread top level structure, if needed.
  64. //
  65. NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
  66. } else if (Status == STATUS_LOG_FILE_FULL) {
  67. NtfsCheckpointForLogFileFull( IrpContext );
  68. }
  69. Status = NtfsCommonLockControl( IrpContext, Irp );
  70. break;
  71. } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
  72. //
  73. // We had some trouble trying to perform the requested
  74. // operation, so we'll abort the I/O request with
  75. // the error status that we get back from the
  76. // execption code
  77. //
  78. Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
  79. }
  80. } while (Status == STATUS_CANT_WAIT ||
  81. Status == STATUS_LOG_FILE_FULL);
  82. ASSERT( IoGetTopLevelIrp() != (PIRP) &TopLevelContext );
  83. FsRtlExitFileSystem();
  84. //
  85. // And return to our caller
  86. //
  87. DebugTrace( -1, Dbg, ("NtfsFsdLockControl -> %08lx\n", Status) );
  88. return Status;
  89. }
  90. BOOLEAN
  91. NtfsFastLock (
  92. IN PFILE_OBJECT FileObject,
  93. IN PLARGE_INTEGER FileOffset,
  94. IN PLARGE_INTEGER Length,
  95. PEPROCESS ProcessId,
  96. ULONG Key,
  97. BOOLEAN FailImmediately,
  98. BOOLEAN ExclusiveLock,
  99. OUT PIO_STATUS_BLOCK IoStatus,
  100. IN PDEVICE_OBJECT DeviceObject
  101. )
  102. /*++
  103. Routine Description:
  104. This is a call back routine for doing the fast lock call.
  105. Arguments:
  106. FileObject - Supplies the file object used in this operation
  107. FileOffset - Supplies the file offset used in this operation
  108. Length - Supplies the length used in this operation
  109. ProcessId - Supplies the process ID used in this operation
  110. Key - Supplies the key used in this operation
  111. FailImmediately - Indicates if the request should fail immediately
  112. if the lock cannot be granted.
  113. ExclusiveLock - Indicates if this is a request for an exclusive or
  114. shared lock
  115. IoStatus - Receives the Status if this operation is successful
  116. Return Value:
  117. BOOLEAN - TRUE if this operation completed and FALSE if caller
  118. needs to take the long route.
  119. --*/
  120. {
  121. BOOLEAN Results;
  122. PSCB Scb;
  123. PFCB Fcb;
  124. BOOLEAN ResourceAcquired = FALSE;
  125. UNREFERENCED_PARAMETER( DeviceObject );
  126. PAGED_CODE();
  127. DebugTrace( +1, Dbg, ("NtfsFastLock\n") );
  128. //
  129. // Decode the type of file object we're being asked to process and
  130. // make sure that is is only a user file open.
  131. //
  132. if ((Scb = NtfsFastDecodeUserFileOpen( FileObject )) == NULL) {
  133. IoStatus->Status = STATUS_INVALID_PARAMETER;
  134. IoStatus->Information = 0;
  135. DebugTrace( -1, Dbg, ("NtfsFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n") );
  136. return TRUE;
  137. }
  138. Fcb = Scb->Fcb;
  139. //
  140. // Acquire shared access to the Fcb this operation can always wait
  141. //
  142. FsRtlEnterFileSystem();
  143. if (Scb->ScbType.Data.FileLock == NULL) {
  144. (VOID) ExAcquireResourceExclusiveLite( Fcb->Resource, TRUE );
  145. ResourceAcquired = TRUE;
  146. } else {
  147. //(VOID) ExAcquireResourceSharedLite( Fcb->Resource, TRUE );
  148. }
  149. try {
  150. //
  151. // We check whether we can proceed
  152. // based on the state of the file oplocks.
  153. //
  154. if ((Scb->ScbType.Data.Oplock != NULL) &&
  155. !FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {
  156. try_return( Results = FALSE );
  157. }
  158. //
  159. // If we don't have a file lock, then get one now.
  160. //
  161. if (Scb->ScbType.Data.FileLock == NULL
  162. && !NtfsCreateFileLock( Scb, FALSE )) {
  163. try_return( Results = FALSE );
  164. }
  165. //
  166. // Now call the FsRtl routine to do the actual processing of the
  167. // Lock request
  168. //
  169. if (Results = FsRtlFastLock( Scb->ScbType.Data.FileLock,
  170. FileObject,
  171. FileOffset,
  172. Length,
  173. ProcessId,
  174. Key,
  175. FailImmediately,
  176. ExclusiveLock,
  177. IoStatus,
  178. NULL,
  179. FALSE )) {
  180. //
  181. // Set the flag indicating if Fast I/O is questionable. We
  182. // only change this flag is the current state is possible.
  183. // Retest again after synchronizing on the header.
  184. //
  185. if (Scb->Header.IsFastIoPossible == FastIoIsPossible) {
  186. NtfsAcquireFsrtlHeader( Scb );
  187. Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
  188. NtfsReleaseFsrtlHeader( Scb );
  189. }
  190. }
  191. try_exit: NOTHING;
  192. } finally {
  193. DebugUnwind( NtfsFastLock );
  194. //
  195. // Release the Fcb, and return to our caller
  196. //
  197. if (ResourceAcquired) {
  198. ExReleaseResourceLite( Fcb->Resource );
  199. }
  200. FsRtlExitFileSystem();
  201. DebugTrace( -1, Dbg, ("NtfsFastLock -> %08lx\n", Results) );
  202. }
  203. return Results;
  204. }
  205. BOOLEAN
  206. NtfsFastUnlockSingle (
  207. IN PFILE_OBJECT FileObject,
  208. IN PLARGE_INTEGER FileOffset,
  209. IN PLARGE_INTEGER Length,
  210. PEPROCESS ProcessId,
  211. ULONG Key,
  212. OUT PIO_STATUS_BLOCK IoStatus,
  213. IN PDEVICE_OBJECT DeviceObject
  214. )
  215. /*++
  216. Routine Description:
  217. This is a call back routine for doing the fast unlock single call.
  218. Arguments:
  219. FileObject - Supplies the file object used in this operation
  220. FileOffset - Supplies the file offset used in this operation
  221. Length - Supplies the length used in this operation
  222. ProcessId - Supplies the process ID used in this operation
  223. Key - Supplies the key used in this operation
  224. Status - Receives the Status if this operation is successful
  225. Return Value:
  226. BOOLEAN - TRUE if this operation completed and FALSE if caller
  227. needs to take the long route.
  228. --*/
  229. {
  230. BOOLEAN Results;
  231. PFCB Fcb;
  232. PSCB Scb;
  233. BOOLEAN ResourceAcquired = FALSE;
  234. UNREFERENCED_PARAMETER( DeviceObject );
  235. PAGED_CODE();
  236. DebugTrace( +1, Dbg, ("NtfsFastUnlockSingle\n") );
  237. IoStatus->Information = 0;
  238. //
  239. // Decode the type of file object we're being asked to process and
  240. // make sure that is is only a user file open.
  241. //
  242. if ((Scb = NtfsFastDecodeUserFileOpen( FileObject )) == NULL) {
  243. IoStatus->Status = STATUS_INVALID_PARAMETER;
  244. DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n") );
  245. return TRUE;
  246. }
  247. Fcb = Scb->Fcb;
  248. //
  249. // Acquire exclusive access to the Fcb this operation can always wait
  250. //
  251. FsRtlEnterFileSystem();
  252. if (Scb->ScbType.Data.FileLock == NULL) {
  253. (VOID) ExAcquireResourceExclusiveLite( Fcb->Resource, TRUE );
  254. ResourceAcquired = TRUE;
  255. } else {
  256. //(VOID) ExAcquireResourceSharedLite( Fcb->Resource, TRUE );
  257. }
  258. try {
  259. //
  260. // We check whether we can proceed based on the state of the file oplocks.
  261. //
  262. if ((Scb->ScbType.Data.Oplock != NULL) &&
  263. !FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {
  264. try_return( Results = FALSE );
  265. }
  266. //
  267. // If we don't have a file lock, then get one now.
  268. //
  269. if (Scb->ScbType.Data.FileLock == NULL
  270. && !NtfsCreateFileLock( Scb, FALSE )) {
  271. try_return( Results = FALSE );
  272. }
  273. //
  274. // Now call the FsRtl routine to do the actual processing of the
  275. // Lock request. The call will always succeed.
  276. //
  277. Results = TRUE;
  278. IoStatus->Status = FsRtlFastUnlockSingle( Scb->ScbType.Data.FileLock,
  279. FileObject,
  280. FileOffset,
  281. Length,
  282. ProcessId,
  283. Key,
  284. NULL,
  285. FALSE );
  286. //
  287. // Set the flag indicating if Fast I/O is possible. We are
  288. // only concerned if there are no longer any filelocks on this
  289. // file.
  290. //
  291. if (!FsRtlAreThereCurrentFileLocks( Scb->ScbType.Data.FileLock ) &&
  292. (Scb->Header.IsFastIoPossible != FastIoIsPossible)) {
  293. NtfsAcquireFsrtlHeader( Scb );
  294. Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
  295. NtfsReleaseFsrtlHeader( Scb );
  296. }
  297. try_exit: NOTHING;
  298. } finally {
  299. DebugUnwind( NtfsFastUnlockSingle );
  300. //
  301. // Release the Fcb, and return to our caller
  302. //
  303. if (ResourceAcquired) {
  304. ExReleaseResourceLite( Fcb->Resource );
  305. }
  306. FsRtlExitFileSystem();
  307. DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> %08lx\n", Results) );
  308. }
  309. return Results;
  310. }
  311. BOOLEAN
  312. NtfsFastUnlockAll (
  313. IN PFILE_OBJECT FileObject,
  314. PEPROCESS ProcessId,
  315. OUT PIO_STATUS_BLOCK IoStatus,
  316. IN PDEVICE_OBJECT DeviceObject
  317. )
  318. /*++
  319. Routine Description:
  320. This is a call back routine for doing the fast unlock all call.
  321. Arguments:
  322. FileObject - Supplies the file object used in this operation
  323. ProcessId - Supplies the process ID used in this operation
  324. Status - Receives the Status if this operation is successful
  325. Return Value:
  326. BOOLEAN - TRUE if this operation completed and FALSE if caller
  327. needs to take the long route.
  328. --*/
  329. {
  330. BOOLEAN Results;
  331. IRP_CONTEXT IrpContext;
  332. TYPE_OF_OPEN TypeOfOpen;
  333. PVCB Vcb;
  334. PFCB Fcb;
  335. PSCB Scb;
  336. PCCB Ccb;
  337. UNREFERENCED_PARAMETER( DeviceObject );
  338. PAGED_CODE();
  339. DebugTrace( +1, Dbg, ("NtfsFastUnlockAll\n") );
  340. IoStatus->Information = 0;
  341. //
  342. // Decode the type of file object we're being asked to process and
  343. // make sure that is is only a user file open.
  344. //
  345. TypeOfOpen = NtfsDecodeFileObject( &IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, FALSE );
  346. if (TypeOfOpen != UserFileOpen) {
  347. IoStatus->Status = STATUS_INVALID_PARAMETER;
  348. IoStatus->Information = 0;
  349. DebugTrace( -1, Dbg, ("NtfsFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n") );
  350. return TRUE;
  351. }
  352. //
  353. // Acquire exclusive access to the Fcb this operation can always wait
  354. //
  355. FsRtlEnterFileSystem();
  356. if (Scb->ScbType.Data.FileLock == NULL) {
  357. (VOID) ExAcquireResourceExclusiveLite( Fcb->Resource, TRUE );
  358. } else {
  359. (VOID) ExAcquireResourceSharedLite( Fcb->Resource, TRUE );
  360. }
  361. try {
  362. //
  363. // We check whether we can proceed based on the state of the file oplocks.
  364. //
  365. if (!FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {
  366. try_return( Results = FALSE );
  367. }
  368. //
  369. // If we don't have a file lock, then get one now.
  370. //
  371. if (Scb->ScbType.Data.FileLock == NULL
  372. && !NtfsCreateFileLock( Scb, FALSE )) {
  373. try_return( Results = FALSE );
  374. }
  375. //
  376. // Now call the FsRtl routine to do the actual processing of the
  377. // Lock request. The call will always succeed.
  378. //
  379. Results = TRUE;
  380. IoStatus->Status = FsRtlFastUnlockAll( Scb->ScbType.Data.FileLock,
  381. FileObject,
  382. ProcessId,
  383. NULL );
  384. //
  385. // Set the flag indicating if Fast I/O is possible
  386. //
  387. NtfsAcquireFsrtlHeader( Scb );
  388. Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
  389. NtfsReleaseFsrtlHeader( Scb );
  390. try_exit: NOTHING;
  391. } finally {
  392. DebugUnwind( NtfsFastUnlockAll );
  393. //
  394. // Release the Fcb, and return to our caller
  395. //
  396. ExReleaseResourceLite( Fcb->Resource );
  397. FsRtlExitFileSystem();
  398. DebugTrace( -1, Dbg, ("NtfsFastUnlockAll -> %08lx\n", Results) );
  399. }
  400. return Results;
  401. }
  402. BOOLEAN
  403. NtfsFastUnlockAllByKey (
  404. IN PFILE_OBJECT FileObject,
  405. PVOID ProcessId,
  406. ULONG Key,
  407. OUT PIO_STATUS_BLOCK IoStatus,
  408. IN PDEVICE_OBJECT DeviceObject
  409. )
  410. /*++
  411. Routine Description:
  412. This is a call back routine for doing the fast unlock all by key call.
  413. Arguments:
  414. FileObject - Supplies the file object used in this operation
  415. ProcessId - Supplies the process ID used in this operation
  416. Key - Supplies the key used in this operation
  417. Status - Receives the Status if this operation is successful
  418. Return Value:
  419. BOOLEAN - TRUE if this operation completed and FALSE if caller
  420. needs to take the long route.
  421. --*/
  422. {
  423. BOOLEAN Results;
  424. IRP_CONTEXT IrpContext;
  425. TYPE_OF_OPEN TypeOfOpen;
  426. PVCB Vcb;
  427. PFCB Fcb;
  428. PSCB Scb;
  429. PCCB Ccb;
  430. UNREFERENCED_PARAMETER( DeviceObject );
  431. PAGED_CODE();
  432. DebugTrace( +1, Dbg, ("NtfsFastUnlockAllByKey\n") );
  433. IoStatus->Information = 0;
  434. //
  435. // Decode the type of file object we're being asked to process and
  436. // make sure that is is only a user file open.
  437. //
  438. TypeOfOpen = NtfsDecodeFileObject( &IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, FALSE );
  439. if (TypeOfOpen != UserFileOpen) {
  440. IoStatus->Status = STATUS_INVALID_PARAMETER;
  441. IoStatus->Information = 0;
  442. DebugTrace( -1, Dbg, ("NtfsFastUnlockAllByKey -> TRUE (STATUS_INVALID_PARAMETER)\n") );
  443. return TRUE;
  444. }
  445. //
  446. // Acquire exclusive access to the Fcb this operation can always wait
  447. //
  448. FsRtlEnterFileSystem();
  449. if (Scb->ScbType.Data.FileLock == NULL) {
  450. (VOID) ExAcquireResourceExclusiveLite( Fcb->Resource, TRUE );
  451. } else {
  452. (VOID) ExAcquireResourceSharedLite( Fcb->Resource, TRUE );
  453. }
  454. try {
  455. //
  456. // We check whether we can proceed based on the state of the file oplocks.
  457. //
  458. if (!FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) {
  459. try_return( Results = FALSE );
  460. }
  461. //
  462. // If we don't have a file lock, then get one now.
  463. //
  464. if (Scb->ScbType.Data.FileLock == NULL
  465. && !NtfsCreateFileLock( Scb, FALSE )) {
  466. try_return( Results = FALSE );
  467. }
  468. //
  469. // Now call the FsRtl routine to do the actual processing of the
  470. // Lock request. The call will always succeed.
  471. //
  472. Results = TRUE;
  473. IoStatus->Status = FsRtlFastUnlockAllByKey( Scb->ScbType.Data.FileLock,
  474. FileObject,
  475. ProcessId,
  476. Key,
  477. NULL );
  478. //
  479. // Set the flag indicating if Fast I/O is possible
  480. //
  481. NtfsAcquireFsrtlHeader( Scb );
  482. Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
  483. NtfsReleaseFsrtlHeader( Scb );
  484. try_exit: NOTHING;
  485. } finally {
  486. DebugUnwind( NtfsFastUnlockAllByKey );
  487. //
  488. // Release the Fcb, and return to our caller
  489. //
  490. ExReleaseResourceLite( Fcb->Resource );
  491. FsRtlExitFileSystem();
  492. DebugTrace( -1, Dbg, ("NtfsFastUnlockAllByKey -> %08lx\n", Results) );
  493. }
  494. return Results;
  495. }
  496. NTSTATUS
  497. NtfsCommonLockControl (
  498. IN PIRP_CONTEXT IrpContext,
  499. IN PIRP Irp
  500. )
  501. /*++
  502. Routine Description:
  503. This is the common routine for Lock Control called by both the fsd and fsp
  504. threads.
  505. Arguments:
  506. Irp - Supplies the Irp to process
  507. Return Value:
  508. NTSTATUS - The return status for the operation
  509. --*/
  510. {
  511. NTSTATUS Status;
  512. PIO_STACK_LOCATION IrpSp;
  513. PFILE_OBJECT FileObject;
  514. TYPE_OF_OPEN TypeOfOpen;
  515. PVCB Vcb;
  516. PFCB Fcb;
  517. PSCB Scb;
  518. PCCB Ccb;
  519. BOOLEAN FcbAcquired = FALSE;
  520. BOOLEAN OplockPostIrp;
  521. ASSERT_IRP_CONTEXT( IrpContext );
  522. ASSERT_IRP( Irp );
  523. ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
  524. PAGED_CODE();
  525. //
  526. // Get a pointer to the current Irp stack location
  527. //
  528. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  529. DebugTrace( +1, Dbg, ("NtfsCommonLockControl\n") );
  530. DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
  531. DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
  532. DebugTrace( 0, Dbg, ("MinorFunction = %08lx\n", IrpSp->MinorFunction) );
  533. //
  534. // Extract and decode the type of file object we're being asked to process
  535. //
  536. FileObject = IrpSp->FileObject;
  537. TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );
  538. //
  539. // If the file is not a user file open then we reject the request
  540. // as an invalid parameter
  541. //
  542. if (TypeOfOpen != UserFileOpen) {
  543. NtfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  544. DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> STATUS_INVALID_PARAMETER\n") );
  545. return STATUS_INVALID_PARAMETER;
  546. }
  547. //
  548. // Acquire exclusive access to the Fcb
  549. //
  550. if (Scb->ScbType.Data.FileLock == NULL) {
  551. NtfsAcquireExclusiveFcb( IrpContext, Fcb, Scb, 0 );
  552. FcbAcquired = TRUE;
  553. } else {
  554. //NtfsAcquireSharedFcb( IrpContext, Fcb, Scb );
  555. }
  556. OplockPostIrp = FALSE;
  557. try {
  558. //
  559. // We check whether we can proceed based on the state of the file oplocks.
  560. // This call might post the irp for us.
  561. //
  562. Status = FsRtlCheckOplock( &Scb->ScbType.Data.Oplock,
  563. Irp,
  564. IrpContext,
  565. NtfsOplockComplete,
  566. NtfsPrePostIrp );
  567. if (Status != STATUS_SUCCESS) {
  568. OplockPostIrp = TRUE;
  569. try_return( NOTHING );
  570. }
  571. //
  572. // If we don't have a file lock, then get one now.
  573. //
  574. if (Scb->ScbType.Data.FileLock == NULL) {
  575. NtfsCreateFileLock( Scb, TRUE );
  576. }
  577. //
  578. // Now call the FsRtl routine to do the actual processing of the
  579. // Lock request
  580. //
  581. Status = FsRtlProcessFileLock( Scb->ScbType.Data.FileLock, Irp, NULL );
  582. //
  583. // Set the flag indicating if Fast I/O is possible
  584. //
  585. NtfsAcquireFsrtlHeader( Scb );
  586. Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
  587. NtfsReleaseFsrtlHeader( Scb );
  588. try_exit: NOTHING;
  589. } finally {
  590. DebugUnwind( NtfsCommonLockControl );
  591. //
  592. // Only if this is not an abnormal termination and we did not post the irp
  593. // do we delete the irp context
  594. //
  595. if (!OplockPostIrp) {
  596. //
  597. // Release the Fcb.
  598. //
  599. if (FcbAcquired) { NtfsReleaseFcb( IrpContext, Fcb ); }
  600. if (!AbnormalTermination()) {
  601. NtfsCompleteRequest( IrpContext, NULL, 0 );
  602. }
  603. }
  604. DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> %08lx\n", Status) );
  605. }
  606. return Status;
  607. }