00050 :
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
00112
00113
00114 requestorMode = KeGetPreviousMode();
00115
00116
00117
00118
00119
00120
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
00139
00140
00141
00142
00143
00144
00145
00146
00147
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
00159
00160
00161
ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine);
00162
00163
00164
00165
00166
00167
00168
ProbeForRead( ByteOffset,
00169
sizeof( LARGE_INTEGER ),
00170
sizeof( ULONG ) );
00171 fileOffset = *ByteOffset;
00172
00173
00174
00175
00176
00177
00178
ProbeForRead( Length,
00179
sizeof( LARGE_INTEGER ),
00180
sizeof( ULONG ) );
00181 length = *Length;
00182
00183
00184
00185
00186
00187
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
00199
00200
00201
00202
00203
ObDereferenceObject( fileObject );
00204
return GetExceptionCode();
00205 }
00206
00207 }
else {
00208
00209
00210
00211
00212
00213
00214 fileOffset = *ByteOffset;
00215 length = *Length;
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
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
00243
00244
00245
00246 deviceObject =
IoGetRelatedDeviceObject( fileObject );
00247 fastIoDispatch = deviceObject->
DriverObject->
FastIoDispatch;
00248
00249
00250
00251
00252
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
00271
00272
00273
try {
00274 *IoStatusBlock = localIoStatus;
00275 } except( EXCEPTION_EXECUTE_HANDLER ) {
00276 localIoStatus.Status = GetExceptionCode();
00277 localIoStatus.Information = 0;
00278 }
00279
00280
00281
00282
00283
00284
if (eventObject) {
00285
KeSetEvent( eventObject, 0, FALSE );
00286
ObDereferenceObject( eventObject );
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00313
00314
00315 fileObject->
LockOperation =
TRUE;
00316
ObDereferenceObject( fileObject );
00317
return localIoStatus.Status;
00318 }
00319 }
00320
00321
00322
00323
00324
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
00351
00352
00353
00354
KeClearEvent( &fileObject->
Event );
00355 fileObject->
LockOperation =
TRUE;
00356
00357
00358
00359
00360
00361
00362 irp =
IoAllocateIrp( deviceObject->
StackSize, TRUE );
00363
if (!irp) {
00364
00365
00366
00367
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
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
00389
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
00399
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
00417
00418
00419
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
00432
00433
00434
00435
IopExceptionCleanup( fileObject,
00436 irp,
00437 eventObject,
00438 (
PKEVENT) NULL );
00439
00440
return GetExceptionCode();
00441 }
00442
00443
00444
00445
00446
00447
00448
return IopSynchronousServiceTail( deviceObject,
00449 irp,
00450 fileObject,
00451 FALSE,
00452 requestorMode,
00453 synchronousIo,
00454 OtherTransfer );
00455 }