00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
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 0
L,
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 }
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
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
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
00511
00512
00513 requestorMode = KeGetPreviousMode();
00514
00515
00516
00517
00518
00519
00520
00521
00522 status =
ObReferenceObjectByHandle( FileHandle,
00523 0
L,
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
00536
00537
00538
00539
if (requestorMode !=
KernelMode) {
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
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
00563
00564
00565
ProbeForWriteIoStatus( IoStatusBlock );
00566
00567
00568
00569
00570
00571
00572
ProbeForRead( ByteOffset,
00573
sizeof( LARGE_INTEGER ),
00574
sizeof( ULONG ) );
00575 fileOffset = *ByteOffset;
00576
00577
00578
00579
00580
00581
00582
ProbeForRead( Length,
00583
sizeof( LARGE_INTEGER ),
00584
sizeof( ULONG ) );
00585 length = *Length;
00586
00587 } except(
EXCEPTION_EXECUTE_HANDLER) {
00588
00589
00590
00591
00592
00593
00594
00595
ObDereferenceObject( fileObject );
00596
return GetExceptionCode();
00597
00598 }
00599
00600 }
else {
00601
00602
00603
00604
00605
00606
00607 fileOffset = *ByteOffset;
00608 length = *Length;
00609 }
00610
00611
00612
00613
00614
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
00626
00627
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
00644
00645
00646
try {
00647 *IoStatusBlock = localIoStatus;
00648 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00649 localIoStatus.Status = GetExceptionCode();
00650 localIoStatus.Information = 0;
00651 }
00652
00653
00654
00655
00656
00657
ObDereferenceObject( fileObject );
00658
return localIoStatus.Status;
00659 }
00660 }
00661
00662
00663
00664
00665
00666
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
00688
00689
00690
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
00704
00705
00706
KeClearEvent( &fileObject->Event );
00707
00708
00709
00710
00711
00712
00713
00714 irp =
IoAllocateIrp( deviceObject->
StackSize,
TRUE );
00715
if (!irp) {
00716
00717
00718
00719
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
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
00750
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
00763
00764
00765
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
00778
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
00795
00796
00797
00798 irpSp->
Parameters.LockControl.Key =
Key;
00799 irpSp->
Parameters.LockControl.ByteOffset = fileOffset;
00800
00801
00802
00803
00804
00805
00806 status =
IopSynchronousServiceTail( deviceObject,
00807 irp,
00808 fileObject,
00809
FALSE,
00810 requestorMode,
00811 synchronousIo,
00812
OtherTransfer );
00813
00814
00815
00816
00817
00818
00819
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 }