Source code of Windows XP (NT5)
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.

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