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.

853 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. lock.c
  5. Abstract:
  6. This module contains the code to implement the NtLockFile and the
  7. NtUnlockFile system services for the NT I/O system.
  8. Author:
  9. Darryl E. Havens (darrylh) 29-Nov-1989
  10. Environment:
  11. Kernel mode only
  12. Revision History:
  13. --*/
  14. #include "iomgr.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, NtLockFile)
  17. #pragma alloc_text(PAGE, NtUnlockFile)
  18. #endif
  19. NTSTATUS
  20. NtLockFile(
  21. IN HANDLE FileHandle,
  22. IN HANDLE Event OPTIONAL,
  23. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  24. IN PVOID ApcContext OPTIONAL,
  25. OUT PIO_STATUS_BLOCK IoStatusBlock,
  26. IN PLARGE_INTEGER ByteOffset,
  27. IN PLARGE_INTEGER Length,
  28. IN ULONG Key,
  29. IN BOOLEAN FailImmediately,
  30. IN BOOLEAN ExclusiveLock
  31. )
  32. /*++
  33. Routine Description:
  34. This service locks a specified range of bytes on the file specified by
  35. the FileHandle parameter. The lock may either be an exclusive lock or
  36. a shared lock. Furthermore, the caller has the option of specifying
  37. whether or not the service should return immediately if the lock cannot
  38. be acquired without waiting.
  39. Arguments:
  40. FileHandle - Supplies a handle to an open file.
  41. Event - Supplies an optional event to be set to the Signaled state when
  42. the operation is complete.
  43. ApcRoutine - Supplies an optional APC routine to be executed when the
  44. operation is complete.
  45. ApcContext - Supplies a context parameter to be passed to the ApcRoutine,
  46. if an ApcRoutine was specified.
  47. IoStatusBlock - Address of the caller's I/O status block.
  48. ByteOffset - Specifies the starting byte offset of the range to lock.
  49. Length - Specifies the length of the byte range to be locked.
  50. Key - Specifies the key to be associated with the lock.
  51. FailImmediately - Specifies that if the lock cannot immediately be
  52. acquired that the service should return to the caller.
  53. ExclusiveLock - Specifies, if TRUE, that the lock should be an exclusive
  54. lock; otherwise the lock is a shared lock.
  55. Return Value:
  56. The status returned is success if the operation was properly queued to
  57. the I/O system. Once the operation completes, the status can be
  58. determined by examining the Status field of the I/O status block.
  59. --*/
  60. {
  61. PIRP irp;
  62. NTSTATUS status;
  63. PFILE_OBJECT fileObject;
  64. PDEVICE_OBJECT deviceObject;
  65. PFAST_IO_DISPATCH fastIoDispatch;
  66. PKEVENT eventObject = (PKEVENT) NULL;
  67. KPROCESSOR_MODE requestorMode;
  68. PIO_STACK_LOCATION irpSp;
  69. LARGE_INTEGER fileOffset;
  70. LARGE_INTEGER length;
  71. ACCESS_MASK grantedAccess;
  72. OBJECT_HANDLE_INFORMATION handleInformation;
  73. BOOLEAN synchronousIo;
  74. PETHREAD CurrentThread;
  75. PAGED_CODE();
  76. //
  77. // Get the previous mode; i.e., the mode of the caller.
  78. //
  79. CurrentThread = PsGetCurrentThread ();
  80. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  81. //
  82. // Reference the file object so the target device can be found and the
  83. // access rights mask can be used in the following checks for callers
  84. // in user mode. Note that if the handle does not refer to a file
  85. // object, then it will fail.
  86. //
  87. status = ObReferenceObjectByHandle( FileHandle,
  88. 0L,
  89. IoFileObjectType,
  90. requestorMode,
  91. (PVOID *) &fileObject,
  92. &handleInformation);
  93. if (!NT_SUCCESS( status )) {
  94. return status;
  95. }
  96. grantedAccess = handleInformation.GrantedAccess;
  97. if (requestorMode != KernelMode) {
  98. //
  99. // The caller's access mode is not kernel so probe each of the arguments
  100. // and capture them as necessary. If any failures occur, the condition
  101. // handler will be invoked to handle them. It will simply cleanup and
  102. // return an access violation status code back to the system service
  103. // dispatcher.
  104. //
  105. //
  106. // Check to ensure that the caller has either READ or WRITE access to
  107. // the file. If not, cleanup and return an error.
  108. //
  109. if (!SeComputeGrantedAccesses( grantedAccess, FILE_READ_DATA | FILE_WRITE_DATA )) {
  110. ObDereferenceObject( fileObject );
  111. return STATUS_ACCESS_DENIED;
  112. }
  113. try {
  114. //
  115. // The IoStatusBlock parameter must be writeable by the caller.
  116. //
  117. ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine);
  118. //
  119. // The ByteOffset parameter must be readable by the caller. Probe
  120. // and capture it.
  121. //
  122. ProbeForReadSmallStructure( ByteOffset,
  123. sizeof( LARGE_INTEGER ),
  124. sizeof( ULONG ) );
  125. fileOffset = *ByteOffset;
  126. //
  127. // Likewise, the Length parameter must also be readable by the
  128. // caller. Probe and capture it as well.
  129. //
  130. ProbeForReadSmallStructure( Length,
  131. sizeof( LARGE_INTEGER ),
  132. sizeof( ULONG ) );
  133. length = *Length;
  134. //
  135. // If this file has an I/O completion port associated w/it, then
  136. // ensure that the caller did not supply an APC routine, as the
  137. // two are mutually exclusive methods for I/O completion
  138. // notification.
  139. //
  140. if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
  141. ObDereferenceObject( fileObject );
  142. return STATUS_INVALID_PARAMETER;
  143. }
  144. } except(EXCEPTION_EXECUTE_HANDLER) {
  145. //
  146. // An exception was incurred attempting to probe the caller's
  147. // parameters. Dereference the file object and return an
  148. // appropriate error status code.
  149. //
  150. ObDereferenceObject( fileObject );
  151. return GetExceptionCode();
  152. }
  153. } else {
  154. //
  155. // The caller's mode was kernel. Get the ByteOffset and Length
  156. // parameter 's to the expected locations.
  157. //
  158. fileOffset = *ByteOffset;
  159. length = *Length;
  160. }
  161. //
  162. // Get the address of the event object and set the event to the Not-
  163. // Signaled state, if an event was specified. Note here, too, that if
  164. // the handle does not refer to an event, or if the event cannot be
  165. // written, then the reference will fail. Since certain legacy
  166. // applications rely on an old bug in Win32's LockFileEx, we must
  167. // tolerate bad event handles.
  168. //
  169. if (ARGUMENT_PRESENT( Event )) {
  170. status = ObReferenceObjectByHandle( Event,
  171. EVENT_MODIFY_STATE,
  172. ExEventObjectType,
  173. requestorMode,
  174. (PVOID *) &eventObject,
  175. NULL );
  176. if (!NT_SUCCESS( status )) {
  177. ASSERT( !eventObject );
  178. } else {
  179. KeClearEvent( eventObject );
  180. }
  181. }
  182. //
  183. // Get the address of the target device object and the fast Io dispatch
  184. // structure.
  185. //
  186. deviceObject = IoGetRelatedDeviceObject( fileObject );
  187. fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  188. //
  189. // Turbo lock support. If the fast Io Dispatch specifies a fast lock
  190. // routine then we'll first try and calling it with the specified lock
  191. // parameters.
  192. //
  193. if (fastIoDispatch && fastIoDispatch->FastIoLock) {
  194. IO_STATUS_BLOCK localIoStatus;
  195. if (fastIoDispatch->FastIoLock( fileObject,
  196. &fileOffset,
  197. &length,
  198. PsGetCurrentProcessByThread(CurrentThread),
  199. Key,
  200. FailImmediately,
  201. ExclusiveLock,
  202. &localIoStatus,
  203. deviceObject )) {
  204. //
  205. // Carefully return the I/O status.
  206. //
  207. try {
  208. #if defined(_WIN64)
  209. //
  210. // If this is a32-bit thread, and the IO request is
  211. // asynchronous, then the IOSB is 32-bit. Wow64 always sends
  212. // the 32-bit IOSB when the I/O is asynchronous.
  213. //
  214. if (IopIsIosb32(ApcRoutine)) {
  215. PIO_STATUS_BLOCK32 UserIosb32 = (PIO_STATUS_BLOCK32)IoStatusBlock;
  216. UserIosb32->Information = (ULONG)localIoStatus.Information;
  217. UserIosb32->Status = (NTSTATUS)localIoStatus.Status;
  218. } else {
  219. *IoStatusBlock = localIoStatus;
  220. }
  221. #else
  222. *IoStatusBlock = localIoStatus;
  223. #endif
  224. } except( EXCEPTION_EXECUTE_HANDLER ) {
  225. localIoStatus.Status = GetExceptionCode();
  226. localIoStatus.Information = 0;
  227. }
  228. //
  229. // If a valid event was specified, set it.
  230. //
  231. if (eventObject) {
  232. KeSetEvent( eventObject, 0, FALSE );
  233. ObDereferenceObject( eventObject );
  234. }
  235. //
  236. // Note that the file object event need not be set to the
  237. // Signaled state, as it is already set.
  238. //
  239. //
  240. // If this file object has a completion port associated with it
  241. // and this request has a non-NULL APC context then a completion
  242. // message needs to be queued.
  243. //
  244. if (fileObject->CompletionContext && ARGUMENT_PRESENT( ApcContext )) {
  245. if (!NT_SUCCESS(IoSetIoCompletion( fileObject->CompletionContext->Port,
  246. fileObject->CompletionContext->Key,
  247. ApcContext,
  248. localIoStatus.Status,
  249. localIoStatus.Information,
  250. TRUE ))) {
  251. localIoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  252. }
  253. }
  254. //
  255. // Cleanup and return.
  256. //
  257. fileObject->LockOperation = TRUE;
  258. ObDereferenceObject( fileObject );
  259. return localIoStatus.Status;
  260. }
  261. }
  262. //
  263. // Make a special check here to determine whether this is a synchronous
  264. // I/O operation. If it is, then wait here until the file is owned by
  265. // the current thread.
  266. //
  267. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  268. BOOLEAN interrupted;
  269. if (!IopAcquireFastLock( fileObject )) {
  270. status = IopAcquireFileObjectLock( fileObject,
  271. requestorMode,
  272. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  273. &interrupted );
  274. if (interrupted) {
  275. if (eventObject) {
  276. ObDereferenceObject( eventObject );
  277. }
  278. ObDereferenceObject( fileObject );
  279. return status;
  280. }
  281. }
  282. synchronousIo = TRUE;
  283. } else {
  284. synchronousIo = FALSE;
  285. }
  286. //
  287. // Set the file object to the Not-Signaled state and mark it as having had
  288. // a lock operation performed on it.
  289. //
  290. KeClearEvent( &fileObject->Event );
  291. fileObject->LockOperation = TRUE;
  292. //
  293. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  294. // The allocation is performed with an exception handler in case the
  295. // caller does not have enough quota to allocate the packet.
  296. irp = IoAllocateIrp( deviceObject->StackSize, TRUE );
  297. if (!irp) {
  298. //
  299. // An IRP could not be allocated. Cleanup and return an appropriate
  300. // error status code.
  301. //
  302. IopAllocateIrpCleanup( fileObject, eventObject );
  303. return STATUS_INSUFFICIENT_RESOURCES;
  304. }
  305. irp->Tail.Overlay.OriginalFileObject = fileObject;
  306. irp->Tail.Overlay.Thread = CurrentThread;
  307. irp->RequestorMode = requestorMode;
  308. //
  309. // Fill in the service independent parameters in the IRP.
  310. //
  311. irp->UserEvent = eventObject;
  312. irp->UserIosb = IoStatusBlock;
  313. irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
  314. irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
  315. //
  316. // Get a pointer to the stack location for the first driver. This will be
  317. // used to pass the original function codes and parameters.
  318. //
  319. irpSp = IoGetNextIrpStackLocation( irp );
  320. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  321. irpSp->MinorFunction = IRP_MN_LOCK;
  322. irpSp->FileObject = fileObject;
  323. //
  324. // Copy the caller's parameters to the service-specific portion of the
  325. // IRP.
  326. //
  327. irpSp->Flags = 0;
  328. if (FailImmediately) {
  329. irpSp->Flags = SL_FAIL_IMMEDIATELY;
  330. }
  331. if (ExclusiveLock) {
  332. irpSp->Flags |= SL_EXCLUSIVE_LOCK;
  333. }
  334. irpSp->Parameters.LockControl.Key = Key;
  335. irpSp->Parameters.LockControl.ByteOffset = fileOffset;
  336. try {
  337. PLARGE_INTEGER lengthBuffer;
  338. //
  339. // Attempt to allocate an intermediary buffer to hold the length of
  340. // this lock operation. If it fails, either because there is no
  341. // more quota, or because there are no more resources, then the
  342. // exception handler will be invoked to cleanup and exit.
  343. //
  344. lengthBuffer = ExAllocatePoolWithQuota( NonPagedPool,
  345. sizeof( LARGE_INTEGER ) );
  346. *lengthBuffer = length;
  347. irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR) lengthBuffer;
  348. irpSp->Parameters.LockControl.Length = lengthBuffer;
  349. } except(EXCEPTION_EXECUTE_HANDLER) {
  350. //
  351. // An exception was incurred. Simply clean everything up and
  352. // return an appropriate error status code.
  353. //
  354. IopExceptionCleanup( fileObject,
  355. irp,
  356. eventObject,
  357. (PKEVENT) NULL );
  358. return GetExceptionCode();
  359. }
  360. //
  361. // Queue the packet, call the driver, and synchronize appopriately with
  362. // I/O completion.
  363. //
  364. return IopSynchronousServiceTail( deviceObject,
  365. irp,
  366. fileObject,
  367. FALSE,
  368. requestorMode,
  369. synchronousIo,
  370. OtherTransfer );
  371. }
  372. NTSTATUS
  373. NtUnlockFile(
  374. IN HANDLE FileHandle,
  375. OUT PIO_STATUS_BLOCK IoStatusBlock,
  376. IN PLARGE_INTEGER ByteOffset,
  377. IN PLARGE_INTEGER Length,
  378. IN ULONG Key
  379. )
  380. /*++
  381. Routine Description:
  382. This service releases the lock associated with the specified byte range
  383. for the file specified by the FileHandle parameter.
  384. Arguments:
  385. FileHandle - Supplies a handle to an open file.
  386. IoStatusBlock - Address of the caller's I/O status block.
  387. ByteOffset - Specifies the byte offset of the range to unlock.
  388. Length - Specifies the length of the byte range to unlock.
  389. Key - Specifies the key associated with the locked range.
  390. Return Value:
  391. The status returned is the final completion status of the operation.
  392. --*/
  393. {
  394. PIRP irp;
  395. NTSTATUS status;
  396. PFILE_OBJECT fileObject;
  397. PDEVICE_OBJECT deviceObject;
  398. PFAST_IO_DISPATCH fastIoDispatch;
  399. PKEVENT event;
  400. KPROCESSOR_MODE requestorMode;
  401. PIO_STACK_LOCATION irpSp;
  402. IO_STATUS_BLOCK localIoStatus;
  403. LARGE_INTEGER fileOffset;
  404. LARGE_INTEGER length;
  405. ACCESS_MASK grantedAccess;
  406. OBJECT_HANDLE_INFORMATION handleInformation;
  407. BOOLEAN synchronousIo;
  408. PETHREAD CurrentThread;
  409. PAGED_CODE();
  410. //
  411. // Get the previous mode; i.e., the mode of the caller.
  412. //
  413. CurrentThread = PsGetCurrentThread ();
  414. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  415. //
  416. // Reference the file object so the target device can be found and the
  417. // access rights mask can be used in the following checks for callers
  418. // in user mode. Note that if the handle does not refer to a file
  419. // object, then it will fail.
  420. //
  421. status = ObReferenceObjectByHandle( FileHandle,
  422. 0L,
  423. IoFileObjectType,
  424. requestorMode,
  425. (PVOID *) &fileObject,
  426. &handleInformation);
  427. if (!NT_SUCCESS( status )) {
  428. return status;
  429. }
  430. grantedAccess = handleInformation.GrantedAccess;
  431. //
  432. // Check to see if the requestor mode was user. If so, perform a bunch
  433. // of extra checks.
  434. //
  435. if (requestorMode != KernelMode) {
  436. //
  437. // The caller's access mode is not kernel so probe each of the arguments
  438. // and capture them as necessary. If any failures occur, the condition
  439. // handler will be invoked to handle them. It will simply cleanup and
  440. // return an access violation status code back to the system service
  441. // dispatcher.
  442. //
  443. //
  444. // Check to ensure that the caller has either READ or WRITE access
  445. // to the file. If not, cleanup and return an error.
  446. //
  447. if (!SeComputeGrantedAccesses( grantedAccess, FILE_READ_DATA | FILE_WRITE_DATA )) {
  448. ObDereferenceObject( fileObject );
  449. return STATUS_ACCESS_DENIED;
  450. }
  451. try {
  452. //
  453. // The IoStatusBlock parameter must be writeable by the caller.
  454. //
  455. ProbeForWriteIoStatus( IoStatusBlock );
  456. //
  457. // The ByteOffset parameter must be readable by the caller. Probe
  458. // and capture it.
  459. //
  460. ProbeForReadSmallStructure( ByteOffset,
  461. sizeof( LARGE_INTEGER ),
  462. sizeof( ULONG ) );
  463. fileOffset = *ByteOffset;
  464. //
  465. // Likewise, the Length parameter must also be readable by the
  466. // caller. Probe and capture it as well.
  467. //
  468. ProbeForReadSmallStructure( Length,
  469. sizeof( LARGE_INTEGER ),
  470. sizeof( ULONG ) );
  471. length = *Length;
  472. } except(EXCEPTION_EXECUTE_HANDLER) {
  473. //
  474. // An exception was incurred while attempting to probe the
  475. // caller's parameters. Dereference the file object and return
  476. // an appropriate error status code.
  477. //
  478. ObDereferenceObject( fileObject );
  479. return GetExceptionCode();
  480. }
  481. } else {
  482. //
  483. // The caller's mode was kernel. Get the ByteOffset and Length
  484. // parameter 's to the expected locations.
  485. //
  486. fileOffset = *ByteOffset;
  487. length = *Length;
  488. }
  489. //
  490. // Get the address of the target device object. If this file represents
  491. // a device that was opened directly, then simply use the device or its
  492. // attached device(s) directly. Also get the fast I/O dispatch address.
  493. //
  494. if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  495. deviceObject = IoGetRelatedDeviceObject( fileObject );
  496. } else {
  497. deviceObject = IoGetAttachedDevice( fileObject->DeviceObject );
  498. }
  499. fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  500. //
  501. // Turbo lock support. If the fast Io Dispatch specifies a fast lock
  502. // routine then we'll first try and calling it with the specified lock
  503. // parameters.
  504. //
  505. if (fastIoDispatch && fastIoDispatch->FastIoUnlockSingle) {
  506. IO_STATUS_BLOCK localIoStatus;
  507. if (fastIoDispatch->FastIoUnlockSingle( fileObject,
  508. &fileOffset,
  509. &length,
  510. PsGetCurrentProcessByThread(CurrentThread),
  511. Key,
  512. &localIoStatus,
  513. deviceObject )) {
  514. //
  515. // Carefully return the I/O status.
  516. //
  517. try {
  518. *IoStatusBlock = localIoStatus;
  519. } except( EXCEPTION_EXECUTE_HANDLER ) {
  520. localIoStatus.Status = GetExceptionCode();
  521. localIoStatus.Information = 0;
  522. }
  523. //
  524. // Cleanup and return.
  525. //
  526. ObDereferenceObject( fileObject );
  527. return localIoStatus.Status;
  528. }
  529. }
  530. //
  531. // Make a special check here to determine whether this is a synchronous
  532. // I/O operation. If it is, then wait here until the file is owned by
  533. // the current thread. If this is not a (serialized) synchronous I/O
  534. // operation, then allocate and initialize the local event.
  535. //
  536. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  537. BOOLEAN interrupted;
  538. if (!IopAcquireFastLock( fileObject )) {
  539. status = IopAcquireFileObjectLock( fileObject,
  540. requestorMode,
  541. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  542. &interrupted );
  543. if (interrupted) {
  544. ObDereferenceObject( fileObject );
  545. return status;
  546. }
  547. }
  548. synchronousIo = TRUE;
  549. } else {
  550. //
  551. // This is a synchronous API being invoked for a file that is opened
  552. // for asynchronous I/O. This means that this system service is
  553. // to synchronize the completion of the operation before returning
  554. // to the caller. A local event is used to do this.
  555. //
  556. event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) );
  557. if (event == NULL) {
  558. ObDereferenceObject( fileObject );
  559. return STATUS_INSUFFICIENT_RESOURCES;
  560. }
  561. KeInitializeEvent( event, SynchronizationEvent, FALSE );
  562. synchronousIo = FALSE;
  563. }
  564. //
  565. // Set the file object to the Not-Signaled state.
  566. //
  567. KeClearEvent( &fileObject->Event );
  568. //
  569. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  570. // The allocation is performed with an exception handler in case the
  571. // caller does not have enough quota to allocate the packet.
  572. //
  573. irp = IoAllocateIrp( deviceObject->StackSize, TRUE );
  574. if (!irp) {
  575. //
  576. // An IRP could not be allocated. Cleanup and return an appropriate
  577. // error status code.
  578. //
  579. if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) {
  580. ExFreePool( event );
  581. }
  582. IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL );
  583. return STATUS_INSUFFICIENT_RESOURCES;
  584. }
  585. irp->Tail.Overlay.OriginalFileObject = fileObject;
  586. irp->Tail.Overlay.Thread = CurrentThread;
  587. irp->RequestorMode = requestorMode;
  588. //
  589. // Fill in the service independent parameters in the IRP.
  590. //
  591. if (synchronousIo) {
  592. irp->UserEvent = (PKEVENT) NULL;
  593. irp->UserIosb = IoStatusBlock;
  594. } else {
  595. irp->UserEvent = event;
  596. irp->UserIosb = &localIoStatus;
  597. irp->Flags = IRP_SYNCHRONOUS_API;
  598. }
  599. irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL;
  600. //
  601. // Get a pointer to the stack location for the first driver. This will
  602. // be used to pass the original function codes and parameters.
  603. //
  604. irpSp = IoGetNextIrpStackLocation( irp );
  605. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  606. irpSp->MinorFunction = IRP_MN_UNLOCK_SINGLE;
  607. irpSp->FileObject = fileObject;
  608. try {
  609. PLARGE_INTEGER lengthBuffer;
  610. //
  611. // Attempt to allocate an intermediary buffer to hold the length of
  612. // this lock operation. If it fails, either because there is no
  613. // more quota, or because there are no more resources, then the
  614. // exception handler will be invoked to cleanup and exit.
  615. //
  616. lengthBuffer = ExAllocatePoolWithQuota( NonPagedPool,
  617. sizeof( LARGE_INTEGER ) );
  618. *lengthBuffer = length;
  619. irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR) lengthBuffer;
  620. irpSp->Parameters.LockControl.Length = lengthBuffer;
  621. } except(EXCEPTION_EXECUTE_HANDLER) {
  622. //
  623. // An exception was incurred. Simply clean everything up and
  624. // return an appropriate error status code.
  625. //
  626. if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) {
  627. ExFreePool( event );
  628. }
  629. IopExceptionCleanup( fileObject,
  630. irp,
  631. NULL,
  632. (PKEVENT) NULL );
  633. return GetExceptionCode();
  634. }
  635. //
  636. // Copy the caller's parameters to the service-specific portion of the
  637. // IRP.
  638. //
  639. irpSp->Parameters.LockControl.Key = Key;
  640. irpSp->Parameters.LockControl.ByteOffset = fileOffset;
  641. //
  642. // Queue the packet, call the driver, and synchronize appopriately with
  643. // I/O completion.
  644. //
  645. status = IopSynchronousServiceTail( deviceObject,
  646. irp,
  647. fileObject,
  648. FALSE,
  649. requestorMode,
  650. synchronousIo,
  651. OtherTransfer );
  652. //
  653. // If the file for this operation was not opened for synchronous I/O, then
  654. // synchronization of completion of the I/O operation has not yet occurred
  655. // since the allocated event must be used for synchronous APIs on files
  656. // opened for asynchronous I/O. Synchronize the completion of the I/O
  657. // operation now.
  658. //
  659. if (!synchronousIo) {
  660. status = IopSynchronousApiServiceTail( status,
  661. event,
  662. irp,
  663. requestorMode,
  664. &localIoStatus,
  665. IoStatusBlock );
  666. }
  667. return status;
  668. }