Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

lock.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989-1993 Microsoft Corporation 00004 00005 Module Name: 00006 00007 lock.c 00008 00009 Abstract: 00010 00011 This module contains the code to implement the NtLockFile and the 00012 NtUnlockFile system services for the NT I/O system. 00013 00014 Author: 00015 00016 Darryl E. Havens (darrylh) 29-Nov-1989 00017 00018 Environment: 00019 00020 Kernel mode only 00021 00022 Revision History: 00023 00024 00025 --*/ 00026 00027 #include "iop.h" 00028 00029 #ifdef ALLOC_PRAGMA 00030 #pragma alloc_text(PAGE, NtLockFile) 00031 #pragma alloc_text(PAGE, NtUnlockFile) 00032 #endif 00033 00034 NTSTATUS 00035 NtLockFile( 00036 IN HANDLE FileHandle, 00037 IN HANDLE Event OPTIONAL, 00038 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 00039 IN PVOID ApcContext OPTIONAL, 00040 OUT PIO_STATUS_BLOCK IoStatusBlock, 00041 IN PLARGE_INTEGER ByteOffset, 00042 IN PLARGE_INTEGER Length, 00043 IN ULONG Key, 00044 IN BOOLEAN FailImmediately, 00045 IN BOOLEAN ExclusiveLock 00046 ) 00047 00048 /*++ 00049 00050 Routine Description: 00051 00052 This service locks a specified range of bytes on the file specified by 00053 the FileHandle parameter. The lock may either be an exclusive lock or 00054 a shared lock. Furthermore, the caller has the option of specifying 00055 whether or not the service should return immediately if the lock cannot 00056 be acquired without waiting. 00057 00058 Arguments: 00059 00060 FileHandle - Supplies a handle to an open file. 00061 00062 Event - Supplies an optional event to be set to the Signaled state when 00063 the operation is complete. 00064 00065 ApcRoutine - Supplies an optional APC routine to be executed when the 00066 operation is complete. 00067 00068 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, 00069 if an ApcRoutine was specified. 00070 00071 IoStatusBlock - Address of the caller's I/O status block. 00072 00073 ByteOffset - Specifies the starting byte offset of the range to lock. 00074 00075 Length - Specifies the length of the byte range to be locked. 00076 00077 Key - Specifies the key to be associated with the lock. 00078 00079 FailImmediately - Specifies that if the lock cannot immediately be 00080 acquired that the service should return to the caller. 00081 00082 ExclusiveLock - Specifies, if TRUE, that the lock should be an exclusive 00083 lock; otherwise the lock is a shared lock. 00084 00085 Return Value: 00086 00087 The status returned is success if the operation was properly queued to 00088 the I/O system. Once the operation completes, the status can be 00089 determined by examining the Status field of the I/O status block. 00090 00091 --*/ 00092 00093 { 00094 PIRP irp; 00095 NTSTATUS status; 00096 PFILE_OBJECT fileObject; 00097 PDEVICE_OBJECT deviceObject; 00098 PFAST_IO_DISPATCH fastIoDispatch; 00099 PKEVENT eventObject = (PKEVENT) NULL; 00100 KPROCESSOR_MODE requestorMode; 00101 PIO_STACK_LOCATION irpSp; 00102 LARGE_INTEGER fileOffset; 00103 LARGE_INTEGER length; 00104 ACCESS_MASK grantedAccess; 00105 OBJECT_HANDLE_INFORMATION handleInformation; 00106 BOOLEAN synchronousIo; 00107 00108 PAGED_CODE(); 00109 00110 // 00111 // Get the previous mode; i.e., the mode of the caller. 00112 // 00113 00114 requestorMode = KeGetPreviousMode(); 00115 00116 // 00117 // Reference the file object so the target device can be found and the 00118 // access rights mask can be used in the following checks for callers 00119 // in user mode. Note that if the handle does not refer to a file 00120 // object, then it will fail. 00121 // 00122 00123 status = ObReferenceObjectByHandle( FileHandle, 00124 0L, 00125 IoFileObjectType, 00126 requestorMode, 00127 (PVOID *) &fileObject, 00128 &handleInformation); 00129 if (!NT_SUCCESS( status )) { 00130 return status; 00131 } 00132 00133 grantedAccess = handleInformation.GrantedAccess; 00134 00135 if (requestorMode != KernelMode) { 00136 00137 // 00138 // The caller's access mode is not kernel so probe each of the arguments 00139 // and capture them as necessary. If any failures occur, the condition 00140 // handler will be invoked to handle them. It will simply cleanup and 00141 // return an access violation status code back to the system service 00142 // dispatcher. 00143 // 00144 00145 // 00146 // Check to ensure that the caller has either READ or WRITE access to 00147 // the file. If not, cleanup and return an error. 00148 // 00149 00150 if (!SeComputeGrantedAccesses( grantedAccess, FILE_READ_DATA | FILE_WRITE_DATA )) { 00151 ObDereferenceObject( fileObject ); 00152 return STATUS_ACCESS_DENIED; 00153 } 00154 00155 try { 00156 00157 // 00158 // The IoStatusBlock parameter must be writeable by the caller. 00159 // 00160 00161 ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine); 00162 00163 // 00164 // The ByteOffset parameter must be readable by the caller. Probe 00165 // and capture it. 00166 // 00167 00168 ProbeForRead( ByteOffset, 00169 sizeof( LARGE_INTEGER ), 00170 sizeof( ULONG ) ); 00171 fileOffset = *ByteOffset; 00172 00173 // 00174 // Likewise, the Length parameter must also be readable by the 00175 // caller. Probe and capture it as well. 00176 // 00177 00178 ProbeForRead( Length, 00179 sizeof( LARGE_INTEGER ), 00180 sizeof( ULONG ) ); 00181 length = *Length; 00182 00183 // 00184 // If this file has an I/O completion port associated w/it, then 00185 // ensure that the caller did not supply an APC routine, as the 00186 // two are mutually exclusive methods for I/O completion 00187 // notification. 00188 // 00189 00190 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 00191 ObDereferenceObject( fileObject ); 00192 return STATUS_INVALID_PARAMETER; 00193 } 00194 00195 } except(EXCEPTION_EXECUTE_HANDLER) { 00196 00197 // 00198 // An exception was incurred attempting to probe the caller's 00199 // parameters. Dereference the file object and return an 00200 // appropriate error status code. 00201 // 00202 00203 ObDereferenceObject( fileObject ); 00204 return GetExceptionCode(); 00205 } 00206 00207 } else { 00208 00209 // 00210 // The caller's mode was kernel. Get the ByteOffset and Length 00211 // parameter 's to the expected locations. 00212 // 00213 00214 fileOffset = *ByteOffset; 00215 length = *Length; 00216 } 00217 00218 // 00219 // Get the address of the event object and set the event to the Not- 00220 // Signaled state, if an event was specified. Note here, too, that if 00221 // the handle does not refer to an event, or if the event cannot be 00222 // written, then the reference will fail. Since certain legacy 00223 // applications rely on an old bug in Win32's LockFileEx, we must 00224 // tolerate bad event handles. 00225 // 00226 00227 if (ARGUMENT_PRESENT( Event )) { 00228 status = ObReferenceObjectByHandle( Event, 00229 EVENT_MODIFY_STATE, 00230 ExEventObjectType, 00231 requestorMode, 00232 (PVOID *) &eventObject, 00233 NULL ); 00234 if (!NT_SUCCESS( status )) { 00235 ASSERT( !eventObject ); 00236 } else { 00237 KeClearEvent( eventObject ); 00238 } 00239 } 00240 00241 // 00242 // Get the address of the target device object and the fast Io dispatch 00243 // structure. 00244 // 00245 00246 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00247 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 00248 00249 // 00250 // Turbo lock support. If the fast Io Dispatch specifies a fast lock 00251 // routine then we'll first try and calling it with the specified lock 00252 // parameters. 00253 // 00254 00255 if (fastIoDispatch && fastIoDispatch->FastIoLock) { 00256 00257 IO_STATUS_BLOCK localIoStatus; 00258 00259 if (fastIoDispatch->FastIoLock( fileObject, 00260 &fileOffset, 00261 &length, 00262 PsGetCurrentProcess(), 00263 Key, 00264 FailImmediately, 00265 ExclusiveLock, 00266 &localIoStatus, 00267 deviceObject )) { 00268 00269 // 00270 // Carefully return the I/O status. 00271 // 00272 00273 try { 00274 *IoStatusBlock = localIoStatus; 00275 } except( EXCEPTION_EXECUTE_HANDLER ) { 00276 localIoStatus.Status = GetExceptionCode(); 00277 localIoStatus.Information = 0; 00278 } 00279 00280 // 00281 // If a valid event was specified, set it. 00282 // 00283 00284 if (eventObject) { 00285 KeSetEvent( eventObject, 0, FALSE ); 00286 ObDereferenceObject( eventObject ); 00287 } 00288 00289 // 00290 // Note that the file object event need not be set to the 00291 // Signaled state, as it is already set. 00292 // 00293 00294 // 00295 // If this file object has a completion port associated with it 00296 // and this request has a non-NULL APC context then a completion 00297 // message needs to be queued. 00298 // 00299 00300 if (fileObject->CompletionContext && ARGUMENT_PRESENT( ApcContext )) { 00301 if (!NT_SUCCESS(IoSetIoCompletion( fileObject->CompletionContext->Port, 00302 fileObject->CompletionContext->Key, 00303 ApcContext, 00304 localIoStatus.Status, 00305 localIoStatus.Information, 00306 TRUE ))) { 00307 localIoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00308 } 00309 } 00310 00311 // 00312 // Cleanup and return. 00313 // 00314 00315 fileObject->LockOperation = TRUE; 00316 ObDereferenceObject( fileObject ); 00317 return localIoStatus.Status; 00318 } 00319 } 00320 00321 // 00322 // Make a special check here to determine whether this is a synchronous 00323 // I/O operation. If it is, then wait here until the file is owned by 00324 // the current thread. 00325 // 00326 00327 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00328 00329 BOOLEAN interrupted; 00330 00331 if (!IopAcquireFastLock( fileObject )) { 00332 status = IopAcquireFileObjectLock( fileObject, 00333 requestorMode, 00334 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00335 &interrupted ); 00336 if (interrupted) { 00337 if (eventObject) { 00338 ObDereferenceObject( eventObject ); 00339 } 00340 ObDereferenceObject( fileObject ); 00341 return status; 00342 } 00343 } 00344 synchronousIo = TRUE; 00345 } else { 00346 synchronousIo = FALSE; 00347 } 00348 00349 // 00350 // Set the file object to the Not-Signaled state and mark it as having had 00351 // a lock operation performed on it. 00352 // 00353 00354 KeClearEvent( &fileObject->Event ); 00355 fileObject->LockOperation = TRUE; 00356 00357 // 00358 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00359 // The allocation is performed with an exception handler in case the 00360 // caller does not have enough quota to allocate the packet. 00361 00362 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00363 if (!irp) { 00364 00365 // 00366 // An IRP could not be allocated. Cleanup and return an appropriate 00367 // error status code. 00368 // 00369 00370 IopAllocateIrpCleanup( fileObject, eventObject ); 00371 00372 return STATUS_INSUFFICIENT_RESOURCES; 00373 } 00374 irp->Tail.Overlay.OriginalFileObject = fileObject; 00375 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00376 irp->RequestorMode = requestorMode; 00377 00378 // 00379 // Fill in the service independent parameters in the IRP. 00380 // 00381 00382 irp->UserEvent = eventObject; 00383 irp->UserIosb = IoStatusBlock; 00384 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 00385 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 00386 00387 // 00388 // Get a pointer to the stack location for the first driver. This will be 00389 // used to pass the original function codes and parameters. 00390 // 00391 00392 irpSp = IoGetNextIrpStackLocation( irp ); 00393 irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL; 00394 irpSp->MinorFunction = IRP_MN_LOCK; 00395 irpSp->FileObject = fileObject; 00396 00397 // 00398 // Copy the caller's parameters to the service-specific portion of the 00399 // IRP. 00400 // 00401 00402 irpSp->Flags = 0; 00403 if (FailImmediately) { 00404 irpSp->Flags = SL_FAIL_IMMEDIATELY; 00405 } 00406 if (ExclusiveLock) { 00407 irpSp->Flags |= SL_EXCLUSIVE_LOCK; 00408 } 00409 irpSp->Parameters.LockControl.Key = Key; 00410 irpSp->Parameters.LockControl.ByteOffset = fileOffset; 00411 00412 try { 00413 PLARGE_INTEGER lengthBuffer; 00414 00415 // 00416 // Attempt to allocate an intermediary buffer to hold the length of 00417 // this lock operation. If it fails, either because there is no 00418 // more quota, or because there are no more resources, then the 00419 // exception handler will be invoked to cleanup and exit. 00420 // 00421 00422 lengthBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00423 sizeof( LARGE_INTEGER ) ); 00424 00425 *lengthBuffer = length; 00426 irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR) lengthBuffer; 00427 irpSp->Parameters.LockControl.Length = lengthBuffer; 00428 } except(EXCEPTION_EXECUTE_HANDLER) { 00429 00430 // 00431 // An exception was incurred. Simply clean everything up and 00432 // return an appropriate error status code. 00433 // 00434 00435 IopExceptionCleanup( fileObject, 00436 irp, 00437 eventObject, 00438 (PKEVENT) NULL ); 00439 00440 return GetExceptionCode(); 00441 } 00442 00443 // 00444 // Queue the packet, call the driver, and synchronize appopriately with 00445 // I/O completion. 00446 // 00447 00448 return IopSynchronousServiceTail( deviceObject, 00449 irp, 00450 fileObject, 00451 FALSE, 00452 requestorMode, 00453 synchronousIo, 00454 OtherTransfer ); 00455 } 00456 00457 NTSTATUS 00458 NtUnlockFile( 00459 IN HANDLE FileHandle, 00460 OUT PIO_STATUS_BLOCK IoStatusBlock, 00461 IN PLARGE_INTEGER ByteOffset, 00462 IN PLARGE_INTEGER Length, 00463 IN ULONG Key 00464 ) 00465 00466 /*++ 00467 00468 Routine Description: 00469 00470 This service releases the lock associated with the specified byte range 00471 for the file specified by the FileHandle parameter. 00472 00473 Arguments: 00474 00475 FileHandle - Supplies a handle to an open file. 00476 00477 IoStatusBlock - Address of the caller's I/O status block. 00478 00479 ByteOffset - Specifies the byte offset of the range to unlock. 00480 00481 Length - Specifies the length of the byte range to unlock. 00482 00483 Key - Specifies the key associated with the locked range. 00484 00485 Return Value: 00486 00487 The status returned is the final completion status of the operation. 00488 00489 --*/ 00490 00491 { 00492 PIRP irp; 00493 NTSTATUS status; 00494 PFILE_OBJECT fileObject; 00495 PDEVICE_OBJECT deviceObject; 00496 PFAST_IO_DISPATCH fastIoDispatch; 00497 PKEVENT event; 00498 KPROCESSOR_MODE requestorMode; 00499 PIO_STACK_LOCATION irpSp; 00500 IO_STATUS_BLOCK localIoStatus; 00501 LARGE_INTEGER fileOffset; 00502 LARGE_INTEGER length; 00503 ACCESS_MASK grantedAccess; 00504 OBJECT_HANDLE_INFORMATION handleInformation; 00505 BOOLEAN synchronousIo; 00506 00507 PAGED_CODE(); 00508 00509 // 00510 // Get the previous mode; i.e., the mode of the caller. 00511 // 00512 00513 requestorMode = KeGetPreviousMode(); 00514 00515 // 00516 // Reference the file object so the target device can be found and the 00517 // access rights mask can be used in the following checks for callers 00518 // in user mode. Note that if the handle does not refer to a file 00519 // object, then it will fail. 00520 // 00521 00522 status = ObReferenceObjectByHandle( FileHandle, 00523 0L, 00524 IoFileObjectType, 00525 requestorMode, 00526 (PVOID *) &fileObject, 00527 &handleInformation); 00528 if (!NT_SUCCESS( status )) { 00529 return status; 00530 } 00531 00532 grantedAccess = handleInformation.GrantedAccess; 00533 00534 // 00535 // Check to see if the requestor mode was user. If so, perform a bunch 00536 // of extra checks. 00537 // 00538 00539 if (requestorMode != KernelMode) { 00540 00541 // 00542 // The caller's access mode is not kernel so probe each of the arguments 00543 // and capture them as necessary. If any failures occur, the condition 00544 // handler will be invoked to handle them. It will simply cleanup and 00545 // return an access violation status code back to the system service 00546 // dispatcher. 00547 // 00548 00549 // 00550 // Check to ensure that the caller has either READ or WRITE access 00551 // to the file. If not, cleanup and return an error. 00552 // 00553 00554 if (!SeComputeGrantedAccesses( grantedAccess, FILE_READ_DATA | FILE_WRITE_DATA )) { 00555 ObDereferenceObject( fileObject ); 00556 return STATUS_ACCESS_DENIED; 00557 } 00558 00559 try { 00560 00561 // 00562 // The IoStatusBlock parameter must be writeable by the caller. 00563 // 00564 00565 ProbeForWriteIoStatus( IoStatusBlock ); 00566 00567 // 00568 // The ByteOffset parameter must be readable by the caller. Probe 00569 // and capture it. 00570 // 00571 00572 ProbeForRead( ByteOffset, 00573 sizeof( LARGE_INTEGER ), 00574 sizeof( ULONG ) ); 00575 fileOffset = *ByteOffset; 00576 00577 // 00578 // Likewise, the Length parameter must also be readable by the 00579 // caller. Probe and capture it as well. 00580 // 00581 00582 ProbeForRead( Length, 00583 sizeof( LARGE_INTEGER ), 00584 sizeof( ULONG ) ); 00585 length = *Length; 00586 00587 } except(EXCEPTION_EXECUTE_HANDLER) { 00588 00589 // 00590 // An exception was incurred while attempting to probe the 00591 // caller's parameters. Dereference the file object and return 00592 // an appropriate error status code. 00593 // 00594 00595 ObDereferenceObject( fileObject ); 00596 return GetExceptionCode(); 00597 00598 } 00599 00600 } else { 00601 00602 // 00603 // The caller's mode was kernel. Get the ByteOffset and Length 00604 // parameter 's to the expected locations. 00605 // 00606 00607 fileOffset = *ByteOffset; 00608 length = *Length; 00609 } 00610 00611 // 00612 // Get the address of the target device object. If this file represents 00613 // a device that was opened directly, then simply use the device or its 00614 // attached device(s) directly. Also get the fast I/O dispatch address. 00615 // 00616 00617 if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { 00618 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00619 } else { 00620 deviceObject = IoGetAttachedDevice( fileObject->DeviceObject ); 00621 } 00622 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 00623 00624 // 00625 // Turbo lock support. If the fast Io Dispatch specifies a fast lock 00626 // routine then we'll first try and calling it with the specified lock 00627 // parameters. 00628 // 00629 00630 if (fastIoDispatch && fastIoDispatch->FastIoUnlockSingle) { 00631 00632 IO_STATUS_BLOCK localIoStatus; 00633 00634 if (fastIoDispatch->FastIoUnlockSingle( fileObject, 00635 &fileOffset, 00636 &length, 00637 PsGetCurrentProcess(), 00638 Key, 00639 &localIoStatus, 00640 deviceObject )) { 00641 00642 // 00643 // Carefully return the I/O status. 00644 // 00645 00646 try { 00647 *IoStatusBlock = localIoStatus; 00648 } except( EXCEPTION_EXECUTE_HANDLER ) { 00649 localIoStatus.Status = GetExceptionCode(); 00650 localIoStatus.Information = 0; 00651 } 00652 00653 // 00654 // Cleanup and return. 00655 // 00656 00657 ObDereferenceObject( fileObject ); 00658 return localIoStatus.Status; 00659 } 00660 } 00661 00662 // 00663 // Make a special check here to determine whether this is a synchronous 00664 // I/O operation. If it is, then wait here until the file is owned by 00665 // the current thread. If this is not a (serialized) synchronous I/O 00666 // operation, then allocate and initialize the local event. 00667 // 00668 00669 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00670 00671 BOOLEAN interrupted; 00672 00673 if (!IopAcquireFastLock( fileObject )) { 00674 status = IopAcquireFileObjectLock( fileObject, 00675 requestorMode, 00676 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00677 &interrupted ); 00678 if (interrupted) { 00679 ObDereferenceObject( fileObject ); 00680 return status; 00681 } 00682 } 00683 synchronousIo = TRUE; 00684 } else { 00685 00686 // 00687 // This is a synchronous API being invoked for a file that is opened 00688 // for asynchronous I/O. This means that this system service is 00689 // to synchronize the completion of the operation before returning 00690 // to the caller. A local event is used to do this. 00691 // 00692 00693 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 00694 if (event == NULL) { 00695 ObDereferenceObject( fileObject ); 00696 return STATUS_INSUFFICIENT_RESOURCES; 00697 } 00698 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 00699 synchronousIo = FALSE; 00700 } 00701 00702 // 00703 // Set the file object to the Not-Signaled state. 00704 // 00705 00706 KeClearEvent( &fileObject->Event ); 00707 00708 // 00709 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00710 // The allocation is performed with an exception handler in case the 00711 // caller does not have enough quota to allocate the packet. 00712 // 00713 00714 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00715 if (!irp) { 00716 00717 // 00718 // An IRP could not be allocated. Cleanup and return an appropriate 00719 // error status code. 00720 // 00721 00722 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00723 ExFreePool( event ); 00724 } 00725 00726 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 00727 00728 return STATUS_INSUFFICIENT_RESOURCES; 00729 } 00730 irp->Tail.Overlay.OriginalFileObject = fileObject; 00731 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00732 irp->RequestorMode = requestorMode; 00733 00734 // 00735 // Fill in the service independent parameters in the IRP. 00736 // 00737 00738 if (synchronousIo) { 00739 irp->UserEvent = (PKEVENT) NULL; 00740 irp->UserIosb = IoStatusBlock; 00741 } else { 00742 irp->UserEvent = event; 00743 irp->UserIosb = &localIoStatus; 00744 irp->Flags = IRP_SYNCHRONOUS_API; 00745 } 00746 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00747 00748 // 00749 // Get a pointer to the stack location for the first driver. This will 00750 // be used to pass the original function codes and parameters. 00751 // 00752 00753 irpSp = IoGetNextIrpStackLocation( irp ); 00754 irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL; 00755 irpSp->MinorFunction = IRP_MN_UNLOCK_SINGLE; 00756 irpSp->FileObject = fileObject; 00757 00758 try { 00759 PLARGE_INTEGER lengthBuffer; 00760 00761 // 00762 // Attempt to allocate an intermediary buffer to hold the length of 00763 // this lock operation. If it fails, either because there is no 00764 // more quota, or because there are no more resources, then the 00765 // exception handler will be invoked to cleanup and exit. 00766 // 00767 00768 lengthBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00769 sizeof( LARGE_INTEGER ) ); 00770 00771 *lengthBuffer = length; 00772 irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR) lengthBuffer; 00773 irpSp->Parameters.LockControl.Length = lengthBuffer; 00774 } except(EXCEPTION_EXECUTE_HANDLER) { 00775 00776 // 00777 // An exception was incurred. Simply clean everything up and 00778 // return an appropriate error status code. 00779 // 00780 00781 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00782 ExFreePool( event ); 00783 } 00784 00785 IopExceptionCleanup( fileObject, 00786 irp, 00787 NULL, 00788 (PKEVENT) NULL ); 00789 00790 return GetExceptionCode(); 00791 } 00792 00793 // 00794 // Copy the caller's parameters to the service-specific portion of the 00795 // IRP. 00796 // 00797 00798 irpSp->Parameters.LockControl.Key = Key; 00799 irpSp->Parameters.LockControl.ByteOffset = fileOffset; 00800 00801 // 00802 // Queue the packet, call the driver, and synchronize appopriately with 00803 // I/O completion. 00804 // 00805 00806 status = IopSynchronousServiceTail( deviceObject, 00807 irp, 00808 fileObject, 00809 FALSE, 00810 requestorMode, 00811 synchronousIo, 00812 OtherTransfer ); 00813 00814 // 00815 // If the file for this operation was not opened for synchronous I/O, then 00816 // synchronization of completion of the I/O operation has not yet occurred 00817 // since the allocated event must be used for synchronous APIs on files 00818 // opened for asynchronous I/O. Synchronize the completion of the I/O 00819 // operation now. 00820 // 00821 00822 if (!synchronousIo) { 00823 00824 status = IopSynchronousApiServiceTail( status, 00825 event, 00826 irp, 00827 requestorMode, 00828 &localIoStatus, 00829 IoStatusBlock ); 00830 } 00831 00832 return status; 00833 }

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7