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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
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
#include "FsRtlP.h"
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #define Dbg (0x20000000)
00095
00096
00097
00098
00099
00100
#ifndef INLINE
00101 #define INLINE __inline
00102
#endif
00103
00104 #define TAG_EXCLUSIVE_LOCK 'xeLF'
00105 #define TAG_FILE_LOCK 'lfLF'
00106 #define TAG_LOCK_INFO 'ilLF'
00107 #define TAG_LOCKTREE_NODE 'nlLF'
00108 #define TAG_SHARED_LOCK 'hsLF'
00109 #define TAG_WAITING_LOCK 'lwLF'
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 FAST_MUTEX FsRtlCreateLockInfo;
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 NPAGED_LOOKASIDE_LIST FsRtlSharedLockLookasideList;
00132 NPAGED_LOOKASIDE_LIST FsRtlExclusiveLockLookasideList;
00133 NPAGED_LOOKASIDE_LIST FsRtlWaitingLockLookasideList;
00134 NPAGED_LOOKASIDE_LIST FsRtlLockTreeNodeLookasideList;
00135 NPAGED_LOOKASIDE_LIST FsRtlLockInfoLookasideList;
00136
00137 PAGED_LOOKASIDE_LIST FsRtlFileLockLookasideList;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 typedef struct _LOCKTREE_NODE {
00196
00197
00198
00199
00200
00201 SINGLE_LIST_ENTRY
Locks;
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 BOOLEAN
HoleyNode;
00215
00216
00217
00218
00219
00220
00221
00222 ULONGLONG
Extent;
00223
00224
00225
00226
00227
00228
00229 RTL_SPLAY_LINKS
Links;
00230
00231
00232
00233
00234
00235 SINGLE_LIST_ENTRY
Tail;
00236
00237 }
LOCKTREE_NODE, *
PLOCKTREE_NODE;
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 typedef struct _SH_LOCK {
00250
00251
00252
00253
00254
00255 SINGLE_LIST_ENTRY
Link;
00256
00257
00258
00259
00260
00261
FILE_LOCK_INFO LockInfo;
00262
00263 }
SH_LOCK, *
PSH_LOCK;
00264
00265
00266
00267
00268
00269
00270 typedef struct _EX_LOCK {
00271
00272
00273
00274
00275
00276 RTL_SPLAY_LINKS
Links;
00277
00278
00279
00280
00281
00282
FILE_LOCK_INFO LockInfo;
00283
00284 }
EX_LOCK, *
PEX_LOCK;
00285
00286
00287
00288
00289
00290
00291
00292 typedef struct _WAITING_LOCK {
00293
00294
00295
00296
00297
00298 SINGLE_LIST_ENTRY
Link;
00299
00300
00301
00302
00303
00304
00305 PVOID
Context;
00306
00307
00308
00309
00310
00311
PIRP Irp;
00312
00313 }
WAITING_LOCK, *
PWAITING_LOCK;
00314
00315
00316
00317
00318
00319
00320 typedef struct _LOCK_QUEUE {
00321
00322
00323
00324
00325
00326 KSPIN_LOCK
QueueSpinLock;
00327
00328
00329
00330
00331
00332
00333 PRTL_SPLAY_LINKS
SharedLockTree;
00334 PRTL_SPLAY_LINKS
ExclusiveLockTree;
00335 SINGLE_LIST_ENTRY
WaitingLocks;
00336 SINGLE_LIST_ENTRY
WaitingLocksTail;
00337
00338 }
LOCK_QUEUE, *
PLOCK_QUEUE;
00339
00340
00341
00342
00343
00344
00345
00346 typedef struct _LOCK_INFO {
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 ULONG
LowestLockOffset;
00360
00361
00362
00363
00364
00365
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine;
00366
00367
00368
00369
00370
00371
PUNLOCK_ROUTINE UnlockRoutine;
00372
00373
00374
00375
00376
00377
LOCK_QUEUE LockQueue;
00378
00379 }
LOCK_INFO, *
PLOCK_INFO;
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
INLINE
00390
PSH_LOCK
00391 FsRtlAllocateSharedLock (
00392 VOID
00393 )
00394 {
00395
return (
PSH_LOCK)
ExAllocateFromNPagedLookasideList( &
FsRtlSharedLockLookasideList );
00396 }
00397
00398
INLINE
00399
PEX_LOCK
00400 FsRtlAllocateExclusiveLock (
00401 VOID
00402 )
00403 {
00404
return (
PEX_LOCK)
ExAllocateFromNPagedLookasideList( &
FsRtlExclusiveLockLookasideList );
00405 }
00406
00407
INLINE
00408
PWAITING_LOCK
00409 FsRtlAllocateWaitingLock (
00410 VOID
00411 )
00412 {
00413
return (
PWAITING_LOCK)
ExAllocateFromNPagedLookasideList( &
FsRtlWaitingLockLookasideList );
00414 }
00415
00416
INLINE
00417
PLOCKTREE_NODE
00418 FsRtlAllocateLockTreeNode (
00419 VOID
00420 )
00421 {
00422
return (
PLOCKTREE_NODE)
ExAllocateFromNPagedLookasideList( &
FsRtlLockTreeNodeLookasideList );
00423 }
00424
00425
INLINE
00426
PLOCK_INFO
00427 FsRtlAllocateLockInfo (
00428 VOID
00429 )
00430 {
00431
return (
PLOCK_INFO)
ExAllocateFromNPagedLookasideList( &
FsRtlLockInfoLookasideList );
00432 }
00433
00434
00435
INLINE
00436
VOID
00437 FsRtlFreeSharedLock (
00438 IN PSH_LOCK C
00439 )
00440 {
00441
ExFreeToNPagedLookasideList( &
FsRtlSharedLockLookasideList, (PVOID)C );
00442 }
00443
00444
INLINE
00445
VOID
00446 FsRtlFreeExclusiveLock (
00447 IN PEX_LOCK C
00448 )
00449 {
00450
ExFreeToNPagedLookasideList( &
FsRtlExclusiveLockLookasideList, (PVOID)C );
00451 }
00452
00453
INLINE
00454
VOID
00455 FsRtlFreeWaitingLock (
00456 IN PWAITING_LOCK C
00457 )
00458 {
00459
ExFreeToNPagedLookasideList( &
FsRtlWaitingLockLookasideList, (PVOID)C );
00460 }
00461
00462
INLINE
00463
VOID
00464 FsRtlFreeLockTreeNode (
00465 IN PLOCKTREE_NODE C
00466 )
00467 {
00468
ExFreeToNPagedLookasideList( &
FsRtlLockTreeNodeLookasideList, (PVOID)C );
00469 }
00470
00471
INLINE
00472
VOID
00473 FsRtlFreeLockInfo (
00474 IN PLOCK_INFO C
00475 )
00476 {
00477
ExFreeToNPagedLookasideList( &
FsRtlLockInfoLookasideList, (PVOID)C );
00478 }
00479
00480
00481 #define FsRtlAcquireLockQueue(a,b) \
00482
ExAcquireSpinLock(&(a)->QueueSpinLock, b);
00483
00484 #define FsRtlReacquireLockQueue(a,b,c) \
00485
ExAcquireSpinLock(&(b)->QueueSpinLock, c);
00486
00487 #define FsRtlReleaseLockQueue(a,b) \
00488
ExReleaseSpinLock(&(a)->QueueSpinLock, b);
00489
00490
00491
00492
00493
00494
00495
00496
00497 #define FsRtlCompleteLockIrp( A, B, C, D, E, F ) \
00498
FsRtlCompleteLockIrpReal( (A)->CompleteLockIrpRoutine, \
00499
B, \
00500
C, \
00501
D, \
00502
E, \
00503
F )
00504
00505
INLINE
00506
VOID
00507 FsRtlCompleteLockIrpReal (
00508 IN
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine,
00509 IN PVOID Context,
00510 IN
PIRP Irp,
00511 IN NTSTATUS Status,
00512 IN PNTSTATUS NewStatus,
00513 IN
PFILE_OBJECT FileObject
00514 )
00515 {
00516
00517
00518
00519
00520
00521
NTSTATUS LocalStatus =
Status;
00522
00523
if (CompleteLockIrpRoutine !=
NULL) {
00524
00525
if (FileObject !=
NULL) {
00526
00527 FileObject->LastLock =
NULL;
00528 }
00529
00530
Irp->
IoStatus.Status = LocalStatus;
00531 *NewStatus = CompleteLockIrpRoutine( Context,
Irp );
00532
00533 }
else {
00534
00535
FsRtlCompleteRequest(
Irp, LocalStatus );
00536 *NewStatus = LocalStatus;
00537 }
00538 }
00539
00540
00541
00542
00543
00544
#ifdef USERTEST
00545
#include <stdio.h>
00546
#include <stdlib.h>
00547
#undef FsRtlAllocateSharedLock
00548
#undef FsRtlAllocateExclusiveLock
00549
#undef FsRtlAllocateLockTreeNode
00550
#undef FsRtlAllocateWaitingLock
00551
#undef FsRtlFreeSharedLock
00552
#undef FsRtlFreeExclusiveLock
00553
#undef FsRtlFreeLockTreeNode
00554
#undef FsRtlFreeWaitingLock
00555
#undef FsRtlAcquireLockQueue
00556
#undef FsRtlReacquireLockQueue
00557
#undef FsRtlReleaseLockQueue
00558
#undef FsRtlCompleteLockIrp
00559
#undef IoCompleteRequest
00560
00561
#define FsRtlAllocateSharedLock( C ) (PSH_LOCK)malloc(sizeof(SH_LOCK))
00562
#define FsRtlAllocateExclusiveLock( C ) (PEX_LOCK)malloc(sizeof(EX_LOCK))
00563
#define FsRtlAllocateLockTreeNode( C ) (PLOCKTREE_NODE)malloc(sizeof(LOCKTREE_NODE))
00564
#define FsRtlAllocateWaitingLock( C ) (PWAITING_LOCK)malloc(sizeof(WAITING_LOCK))
00565
#define FsRtlAllocateLockInfo( C ) (PLOCK_INFO)malloc(sizeof(LOCK_INFO))
00566
#define FsRtlFreeSharedLock( C ) free(C)
00567
#define FsRtlFreeExclusiveLock( C ) free(C)
00568
#define FsRtlFreeLockTreeNode( C ) free(C)
00569
#define FsRtlFreeWaitingLock( C ) free(C)
00570
#define FsRtlFreeLockInfo( C ) free(C)
00571
#define FsRtlAcquireLockQueue(a,b) (*(b) = '\0')
00572
#define FsRtlReacquireLockQueue(a,b,c) (*(c) = '\0')
00573
#define FsRtlReleaseLockQueue(a,b)
00574
#define FsRtlCompleteLockIrp(_FileLock, _Context, _Irp, _Status, _NewStatus, _FileObject) \
00575
{ \
00576
DbgBreakPoint(); \
00577
*_NewStatus = STATUS_SUCCESS; \
00578
}
00579
00580
#define ExReleaseFastMutex(M)
00581
#define ExAcquireFastMutex(M)
00582
#define KeInitializeSpinLock(L)
00583
#define KfRaiseIrql(L) ('\0')
00584
#define KfLowerIrql(I)
00585
#define IoAcquireCancelSpinLock(I)
00586
#define IoReleaseCancelSpinLock(I)
00587
#define IoCompleteRequest(I, S)
00588
#endif
00589
00590
00591
00592
00593
00594
VOID
00595
FsRtlSplitLocks (
00596 IN PLOCKTREE_NODE ParentNode,
00597 IN PSINGLE_LIST_ENTRY *pStartLink,
00598 IN PLARGE_INTEGER LastShadowedByte,
00599 IN PLARGE_INTEGER GlueOffset
00600 );
00601
00602 PRTL_SPLAY_LINKS
00603
FsRtlFindFirstOverlappingSharedNode (
00604 IN PRTL_SPLAY_LINKS Tree,
00605 IN PLARGE_INTEGER StartingByte,
00606 IN PLARGE_INTEGER EndingByte,
00607 IN OUT PRTL_SPLAY_LINKS *LastEdgeNode,
00608 IN OUT PBOOLEAN GreaterThan
00609 );
00610
00611 PRTL_SPLAY_LINKS
00612
FsRtlFindFirstOverlappingExclusiveNode (
00613 IN PRTL_SPLAY_LINKS Tree,
00614 IN PLARGE_INTEGER StartingByte,
00615 IN PLARGE_INTEGER EndingByte,
00616 IN OUT PRTL_SPLAY_LINKS *LastEdgeNode,
00617 IN OUT PBOOLEAN GreaterThan
00618 );
00619
00620
PSH_LOCK
00621
FsRtlFindFirstOverlapInNode (
00622 IN PLOCKTREE_NODE Node,
00623 IN PLARGE_INTEGER StartingByte,
00624 IN PLARGE_INTEGER EndingByte
00625 );
00626
00627 BOOLEAN
00628
FsRtlPrivateInsertLock (
00629 IN PLOCK_INFO LockInfo,
00630 IN
PFILE_OBJECT FileObject,
00631 IN
PFILE_LOCK_INFO FileLockInfo
00632 );
00633
00634 BOOLEAN
00635
FsRtlPrivateInsertSharedLock (
00636 IN PLOCK_QUEUE LockQueue,
00637 IN PSH_LOCK NewLock
00638 );
00639
00640
VOID
00641
FsRtlPrivateInsertExclusiveLock (
00642 IN PLOCK_QUEUE LockQueue,
00643 IN PEX_LOCK NewLock
00644 );
00645
00646
VOID
00647
FsRtlPrivateCheckWaitingLocks (
00648 IN PLOCK_INFO LockInfo,
00649 IN PLOCK_QUEUE LockQueue,
00650 IN KIRQL OldIrql
00651 );
00652
00653
VOID
00654
FsRtlPrivateCancelFileLockIrp (
00655 IN
PDEVICE_OBJECT DeviceObject,
00656 IN
PIRP Irp
00657 );
00658
00659 BOOLEAN
00660
FsRtlPrivateCheckForExclusiveLockAccess (
00661 IN PLOCK_QUEUE LockInfo,
00662 IN
PFILE_LOCK_INFO FileLockInfo
00663 );
00664
00665 BOOLEAN
00666
FsRtlPrivateCheckForSharedLockAccess (
00667 IN PLOCK_QUEUE LockInfo,
00668 IN
PFILE_LOCK_INFO FileLockInfo
00669 );
00670
00671
NTSTATUS
00672
FsRtlPrivateFastUnlockAll (
00673 IN
PFILE_LOCK FileLock,
00674 IN
PFILE_OBJECT FileObject,
00675 IN
PEPROCESS ProcessId,
00676 IN ULONG Key,
00677 IN BOOLEAN MatchKey,
00678 IN PVOID Context OPTIONAL
00679 );
00680
00681 BOOLEAN
00682
FsRtlPrivateInitializeFileLock (
00683 IN
PFILE_LOCK FileLock,
00684 IN BOOLEAN ViaFastCall
00685 );
00686
00687
VOID
00688
FsRtlPrivateRemoveLock (
00689 IN PLOCK_INFO LockInfo,
00690 IN
PFILE_LOCK_INFO,
00691 IN BOOLEAN CheckForWaiters
00692 );
00693
00694 BOOLEAN
00695
FsRtlCheckNoSharedConflict (
00696 IN PLOCK_QUEUE LockQueue,
00697 IN PLARGE_INTEGER Starting,
00698 IN PLARGE_INTEGER Ending
00699 );
00700
00701 BOOLEAN
00702
FsRtlCheckNoExclusiveConflict (
00703 IN PLOCK_QUEUE LockQueue,
00704 IN PLARGE_INTEGER Starting,
00705 IN PLARGE_INTEGER Ending,
00706 IN ULONG Key,
00707 IN
PFILE_OBJECT FileObject,
00708 IN PVOID ProcessId
00709 );
00710
00711
VOID
00712
FsRtlPrivateResetLowestLockOffset (
00713 PLOCK_INFO LockInfo
00714 );
00715
00716
NTSTATUS
00717
FsRtlFastUnlockSingleShared (
00718 IN PLOCK_INFO LockInfo,
00719 IN
PFILE_OBJECT FileObject,
00720 IN LARGE_INTEGER UNALIGNED *FileOffset,
00721 IN PLARGE_INTEGER Length,
00722 IN
PEPROCESS ProcessId,
00723 IN ULONG Key,
00724 IN PVOID Context OPTIONAL,
00725 IN BOOLEAN IgnoreUnlockRoutine,
00726 IN BOOLEAN CheckForWaiters
00727 );
00728
00729
NTSTATUS
00730
FsRtlFastUnlockSingleExclusive (
00731 IN PLOCK_INFO LockInfo,
00732 IN
PFILE_OBJECT FileObject,
00733 IN LARGE_INTEGER UNALIGNED *FileOffset,
00734 IN PLARGE_INTEGER Length,
00735 IN
PEPROCESS ProcessId,
00736 IN ULONG Key,
00737 IN PVOID Context OPTIONAL,
00738 IN BOOLEAN IgnoreUnlockRoutine,
00739 IN BOOLEAN CheckForWaiters
00740 );
00741
00742
00743
VOID
00744 FsRtlInitializeFileLocks (
00745 VOID
00746 )
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 {
00763
#ifndef USERTEST
00764
00765
00766
00767
00768
00769
ExInitializeNPagedLookasideList( &
FsRtlSharedLockLookasideList,
00770
NULL,
00771
NULL,
00772 0,
00773
sizeof(
SH_LOCK),
00774
TAG_SHARED_LOCK,
00775 16 );
00776
00777
ExInitializeNPagedLookasideList( &
FsRtlExclusiveLockLookasideList,
00778
NULL,
00779
NULL,
00780 0,
00781
sizeof(
EX_LOCK),
00782
TAG_EXCLUSIVE_LOCK,
00783 16 );
00784
00785
ExInitializeNPagedLookasideList( &
FsRtlWaitingLockLookasideList,
00786
NULL,
00787
NULL,
00788 0,
00789
sizeof(
WAITING_LOCK),
00790
TAG_WAITING_LOCK,
00791 16 );
00792
00793
ExInitializeNPagedLookasideList( &
FsRtlLockTreeNodeLookasideList,
00794
NULL,
00795
NULL,
00796 0,
00797
sizeof(
LOCKTREE_NODE),
00798
TAG_LOCKTREE_NODE,
00799 16 );
00800
00801
ExInitializeNPagedLookasideList( &
FsRtlLockInfoLookasideList,
00802
NULL,
00803
NULL,
00804 0,
00805
sizeof(
LOCK_INFO),
00806
TAG_LOCK_INFO,
00807 8 );
00808
00809
ExInitializePagedLookasideList( &
FsRtlFileLockLookasideList,
00810
NULL,
00811
NULL,
00812 0,
00813
sizeof(
FILE_LOCK),
00814
TAG_FILE_LOCK,
00815 8 );
00816
00817
00818
00819
00820
00821
ExInitializeFastMutex(&
FsRtlCreateLockInfo);
00822
00823
00824
#endif
00825
}
00826
00827
00828
VOID
00829 FsRtlInitializeFileLock (
00830 IN
PFILE_LOCK FileLock,
00831 IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
00832 IN
PUNLOCK_ROUTINE UnlockRoutine OPTIONAL
00833 )
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 {
00865
DebugTrace(+1,
Dbg,
"FsRtlInitializeFileLock, FileLock = %08lx\n", FileLock);
00866
00867
00868
00869
00870
00871 FileLock->LockInformation =
NULL;
00872 FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
00873 FileLock->UnlockRoutine = UnlockRoutine;
00874
00875 FileLock->FastIoIsQuestionable =
FALSE;
00876
00877
00878
00879
00880
00881
DebugTrace(-1,
Dbg,
"FsRtlInitializeFileLock -> VOID\n", 0 );
00882
00883
return;
00884 }
00885
00886
00887 BOOLEAN
00888 FsRtlPrivateInitializeFileLock (
00889 IN
PFILE_LOCK FileLock,
00890 IN BOOLEAN ViaFastCall
00891 )
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 {
00914
PLOCK_INFO LockInfo;
00915 BOOLEAN Results =
FALSE;
00916
00917 ExAcquireFastMutex( &
FsRtlCreateLockInfo );
00918
00919
try {
00920
00921
if (FileLock->LockInformation !=
NULL) {
00922
00923
00924
00925
00926
00927
try_return( Results =
TRUE );
00928 }
00929
00930
00931
00932
00933
00934
00935 LockInfo =
FsRtlAllocateLockInfo();
00936
00937
if (LockInfo ==
NULL) {
00938
00939
if (ViaFastCall) {
00940
00941
try_return( Results =
FALSE );
00942
00943 }
else {
00944
00945
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
00946 }
00947 }
00948
00949
00950
00951
00952
00953
00954 LockInfo->
LowestLockOffset = 0xffffffff;
00955
00956
KeInitializeSpinLock( &LockInfo->
LockQueue.
QueueSpinLock );
00957 LockInfo->
LockQueue.
SharedLockTree =
NULL;
00958 LockInfo->
LockQueue.
ExclusiveLockTree =
NULL;
00959 LockInfo->
LockQueue.
WaitingLocks.Next =
NULL;
00960 LockInfo->
LockQueue.
WaitingLocksTail.Next =
NULL;
00961
00962
00963
00964
00965
00966
00967 LockInfo->
CompleteLockIrpRoutine = FileLock->CompleteLockIrpRoutine;
00968 LockInfo->
UnlockRoutine = FileLock->UnlockRoutine;
00969
00970
00971
00972
00973
00974 FileLock->LastReturnedLockInfo.FileObject =
NULL;
00975 FileLock->LastReturnedLock =
NULL;
00976
00977
00978
00979
00980
00981 FileLock->LockInformation = (PVOID) LockInfo;
00982 Results =
TRUE;
00983
00984 try_exit: NOTHING;
00985 } finally {
00986
00987 ExReleaseFastMutex( &
FsRtlCreateLockInfo );
00988 }
00989
00990
return Results;
00991 }
00992
00993
00994
VOID
00995 FsRtlUninitializeFileLock (
00996 IN
PFILE_LOCK FileLock
00997 )
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 {
01021
PLOCK_INFO LockInfo;
01022
PSH_LOCK ShLock;
01023
PEX_LOCK ExLock;
01024 PSINGLE_LIST_ENTRY Link;
01025
PWAITING_LOCK WaitingLock;
01026
PLOCKTREE_NODE LockTreeNode;
01027
PIRP Irp;
01028
NTSTATUS NewStatus;
01029 KIRQL OldIrql;
01030 PKPRCB Prcb;
01031
01032
DebugTrace(+1,
Dbg,
"FsRtlUninitializeFileLock, FileLock = %08lx\n", FileLock);
01033
01034
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
01035
return ;
01036 }
01037
01038
01039
01040
01041
01042
FsRtlAcquireLockQueue(&LockInfo->
LockQueue, &OldIrql);
01043
01044
01045
01046
01047
01048
while (LockInfo->
LockQueue.
SharedLockTree !=
NULL) {
01049
01050 LockTreeNode = CONTAINING_RECORD(LockInfo->
LockQueue.
SharedLockTree,
LOCKTREE_NODE, Links);
01051
01052
01053
01054
01055
01056
while (LockTreeNode->
Locks.Next !=
NULL) {
01057 Link = PopEntryList (&LockTreeNode->
Locks);
01058 ShLock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
01059
01060
FsRtlFreeSharedLock(ShLock);
01061 }
01062
01063
01064
01065
01066
01067
RtlDeleteNoSplay(&LockTreeNode->
Links, &LockInfo->
LockQueue.
SharedLockTree);
01068
01069
FsRtlFreeLockTreeNode(LockTreeNode);
01070 }
01071
01072
while (LockInfo->
LockQueue.
ExclusiveLockTree !=
NULL) {
01073
01074 ExLock = CONTAINING_RECORD(LockInfo->
LockQueue.
ExclusiveLockTree,
EX_LOCK, Links);
01075
01076
RtlDeleteNoSplay(&ExLock->
Links, &LockInfo->
LockQueue.
ExclusiveLockTree);
01077
01078
FsRtlFreeExclusiveLock(ExLock);
01079 }
01080
01081
01082
01083
01084
01085
while (LockInfo->
LockQueue.
WaitingLocks.Next !=
NULL) {
01086
01087 Link = PopEntryList( &LockInfo->
LockQueue.
WaitingLocks );
01088 WaitingLock = CONTAINING_RECORD( Link,
WAITING_LOCK, Link );
01089
01090
Irp = WaitingLock->
Irp;
01091
01092
01093
01094
01095
01096
01097
01098
FsRtlReleaseLockQueue (&LockInfo->
LockQueue, OldIrql);
01099
01100
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
01101
IoSetCancelRoutine(
Irp,
NULL );
01102
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
01103
01104
Irp->
IoStatus.Information = 0;
01105
01106
FsRtlCompleteLockIrp(
01107 LockInfo,
01108 WaitingLock->
Context,
01109
Irp,
01110 STATUS_RANGE_NOT_LOCKED,
01111 &NewStatus,
01112
NULL );
01113
01114
FsRtlAcquireLockQueue(&LockInfo->
LockQueue, &OldIrql);
01115
FsRtlFreeWaitingLock( WaitingLock );
01116 }
01117
01118
01119
01120
01121
01122
FsRtlReleaseLockQueue( &LockInfo->
LockQueue, OldIrql );
01123
FsRtlFreeLockInfo( LockInfo );
01124
01125
01126
01127
01128
01129 FileLock->LockInformation =
NULL;
01130
01131
01132
01133
01134
01135
DebugTrace(-1,
Dbg,
"FsRtlUninitializeFileLock -> VOID\n", 0 );
01136
return;
01137 }
01138
01139
01140
PFILE_LOCK
01141 FsRtlAllocateFileLock (
01142 IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
01143 IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL
01144
01145 )
01146 {
01147
PFILE_LOCK FileLock;
01148
01149 FileLock =
ExAllocateFromPagedLookasideList( &
FsRtlFileLockLookasideList );
01150
01151
if (FileLock !=
NULL) {
01152
01153
FsRtlInitializeFileLock( FileLock,
01154 CompleteLockIrpRoutine,
01155 UnlockRoutine );
01156 }
01157
01158
return FileLock;
01159 }
01160
01161
VOID
01162 FsRtlFreeFileLock (
01163 IN
PFILE_LOCK FileLock
01164 )
01165 {
01166
FsRtlUninitializeFileLock( FileLock );
01167
01168
ExFreeToPagedLookasideList( &
FsRtlFileLockLookasideList, FileLock );
01169 }
01170
01171
01172
NTSTATUS
01173 FsRtlProcessFileLock (
01174 IN
PFILE_LOCK FileLock,
01175 IN
PIRP Irp,
01176 IN PVOID Context OPTIONAL
01177 )
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 {
01206
PIO_STACK_LOCATION IrpSp;
01207
01208 IO_STATUS_BLOCK Iosb;
01209
NTSTATUS Status;
01210 LARGE_INTEGER ByteOffset;
01211
01212
DebugTrace(+1,
Dbg,
"FsRtlProcessFileLock, FileLock = %08lx\n", FileLock);
01213
01214 Iosb.Information = 0;
01215
01216
01217
01218
01219
01220
01221 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01222
01223
ASSERT( IrpSp->
MajorFunction ==
IRP_MJ_LOCK_CONTROL );
01224
01225
01226
01227
01228
01229
switch (IrpSp->
MinorFunction) {
01230
01231
case IRP_MN_LOCK:
01232
01233 ByteOffset = IrpSp->
Parameters.LockControl.ByteOffset;
01234
01235 (
VOID)
FsRtlPrivateLock( FileLock,
01236 IrpSp->
FileObject,
01237 &ByteOffset,
01238 IrpSp->
Parameters.LockControl.Length,
01239
IoGetRequestorProcess(
Irp),
01240 IrpSp->
Parameters.LockControl.Key,
01241
BooleanFlagOn(IrpSp->
Flags,
SL_FAIL_IMMEDIATELY),
01242
BooleanFlagOn(IrpSp->
Flags,
SL_EXCLUSIVE_LOCK),
01243 &Iosb,
01244
Irp,
01245 Context,
01246
FALSE );
01247
01248
break;
01249
01250
case IRP_MN_UNLOCK_SINGLE:
01251
01252 ByteOffset = IrpSp->
Parameters.LockControl.ByteOffset;
01253
01254 Iosb.Status =
FsRtlFastUnlockSingle( FileLock,
01255 IrpSp->
FileObject,
01256 &ByteOffset,
01257 IrpSp->
Parameters.LockControl.Length,
01258
IoGetRequestorProcess(
Irp),
01259 IrpSp->
Parameters.LockControl.Key,
01260 Context,
01261
FALSE );
01262
01263
FsRtlCompleteLockIrp( FileLock, Context,
Irp, Iosb.Status, &
Status,
NULL );
01264
break;
01265
01266
case IRP_MN_UNLOCK_ALL:
01267
01268 Iosb.Status =
FsRtlFastUnlockAll( FileLock,
01269 IrpSp->
FileObject,
01270
IoGetRequestorProcess(
Irp),
01271 Context );
01272
01273
FsRtlCompleteLockIrp( FileLock, Context,
Irp, Iosb.Status, &
Status,
NULL );
01274
break;
01275
01276
case IRP_MN_UNLOCK_ALL_BY_KEY:
01277
01278 Iosb.Status =
FsRtlFastUnlockAllByKey( FileLock,
01279 IrpSp->
FileObject,
01280
IoGetRequestorProcess(
Irp),
01281 IrpSp->
Parameters.LockControl.Key,
01282 Context );
01283
01284
FsRtlCompleteLockIrp( FileLock, Context,
Irp, Iosb.Status, &
Status,
NULL );
01285
break;
01286
01287
default:
01288
01289
01290
01291
01292
01293
01294
01295
DebugTrace(0, 1,
"Invalid LockFile Minor Function Code %08lx\n", IrpSp->
MinorFunction);
01296
01297
01298
FsRtlCompleteRequest(
Irp, STATUS_INVALID_DEVICE_REQUEST );
01299
01300 Iosb.Status = STATUS_INVALID_DEVICE_REQUEST;
01301
break;
01302 }
01303
01304
01305
01306
01307
01308
DebugTrace(-1,
Dbg,
"FsRtlProcessFileLock -> %08lx\n", Iosb.Status);
01309
01310
return Iosb.Status;
01311 }
01312
01313
01314 BOOLEAN
01315 FsRtlCheckLockForReadAccess (
01316 IN
PFILE_LOCK FileLock,
01317 IN
PIRP Irp
01318 )
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342 {
01343 BOOLEAN Result;
01344
01345
PIO_STACK_LOCATION IrpSp;
01346
01347
PLOCK_INFO LockInfo;
01348 LARGE_INTEGER StartingByte;
01349 LARGE_INTEGER Length;
01350 ULONG
Key;
01351
PFILE_OBJECT FileObject;
01352 PVOID ProcessId;
01353 LARGE_INTEGER BeyondLastByte;
01354
01355
DebugTrace(+1,
Dbg,
"FsRtlCheckLockForReadAccess, FileLock = %08lx\n", FileLock);
01356
01357
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
01358
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForReadAccess (No current lock info) -> TRUE\n", 0);
01359
return TRUE;
01360 }
01361
01362
01363
01364
01365
01366
if (LockInfo->
LockQueue.
ExclusiveLockTree ==
NULL) {
01367
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForReadAccess (No current locks) -> TRUE\n", 0);
01368
return TRUE;
01369 }
01370
01371
01372
01373
01374
01375 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01376
01377 StartingByte = IrpSp->
Parameters.Read.ByteOffset;
01378 (ULONGLONG)Length.QuadPart = (ULONGLONG)IrpSp->
Parameters.Read.Length;
01379
01380 (ULONGLONG)BeyondLastByte.QuadPart = (ULONGLONG)StartingByte.QuadPart + Length.LowPart;
01381
if ( (ULONGLONG)BeyondLastByte.QuadPart <= (ULONGLONG)LockInfo->
LowestLockOffset ) {
01382
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForReadAccess (Below lowest lock) -> TRUE\n", 0);
01383
return TRUE;
01384 }
01385
01386
01387
01388
01389
01390
Key = IrpSp->
Parameters.Read.Key;
01391 FileObject = IrpSp->
FileObject;
01392 ProcessId =
IoGetRequestorProcess(
Irp );
01393
01394
01395
01396
01397
01398 Result =
FsRtlFastCheckLockForRead( FileLock,
01399 &StartingByte,
01400 &Length,
01401
Key,
01402 FileObject,
01403 ProcessId );
01404
01405
01406
01407
01408
01409
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForReadAccess -> %08lx\n", Result);
01410
01411
return Result;
01412 }
01413
01414
01415 BOOLEAN
01416 FsRtlCheckLockForWriteAccess (
01417 IN
PFILE_LOCK FileLock,
01418 IN
PIRP Irp
01419 )
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443 {
01444 BOOLEAN Result;
01445
01446
PIO_STACK_LOCATION IrpSp;
01447
01448
PLOCK_INFO LockInfo;
01449 LARGE_INTEGER StartingByte;
01450 LARGE_INTEGER Length;
01451 ULONG
Key;
01452
PFILE_OBJECT FileObject;
01453 PVOID ProcessId;
01454 LARGE_INTEGER BeyondLastByte;
01455
01456
DebugTrace(+1,
Dbg,
"FsRtlCheckLockForWriteAccess, FileLock = %08lx\n", FileLock);
01457
01458
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
01459
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForWriteAccess (No current lock info) -> TRUE\n", 0);
01460
return TRUE;
01461 }
01462
01463
01464
01465
01466
01467
if (LockInfo->
LockQueue.
ExclusiveLockTree ==
NULL && LockInfo->
LockQueue.
SharedLockTree ==
NULL) {
01468
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForWriteAccess (No current locks) -> TRUE\n", 0);
01469
return TRUE;
01470 }
01471
01472
01473
01474
01475
01476 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01477
01478 StartingByte = IrpSp->
Parameters.Write.ByteOffset;
01479 (ULONGLONG)Length.QuadPart = (ULONGLONG)IrpSp->
Parameters.Write.Length;
01480
01481 (ULONGLONG)BeyondLastByte.QuadPart = (ULONGLONG)StartingByte.QuadPart + Length.LowPart;
01482
if ( (ULONGLONG)BeyondLastByte.QuadPart <= (ULONGLONG)LockInfo->
LowestLockOffset ) {
01483
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForWriteAccess (Below lowest lock) -> TRUE\n", 0);
01484
return TRUE;
01485 }
01486
01487
01488
01489
01490
01491
Key = IrpSp->
Parameters.Write.Key;
01492 FileObject = IrpSp->
FileObject;
01493 ProcessId =
IoGetRequestorProcess(
Irp );
01494
01495
01496
01497
01498
01499 Result =
FsRtlFastCheckLockForWrite( FileLock,
01500 &StartingByte,
01501 &Length,
01502
Key,
01503 FileObject,
01504 ProcessId );
01505
01506
01507
01508
01509
01510
DebugTrace(-1,
Dbg,
"FsRtlCheckLockForWriteAccess -> %08lx\n", Result);
01511
01512
return Result;
01513 }
01514
01515
01516 PRTL_SPLAY_LINKS
01517 FsRtlFindFirstOverlappingSharedNode (
01518 IN PRTL_SPLAY_LINKS Tree,
01519 IN PLARGE_INTEGER StartingByte,
01520 IN PLARGE_INTEGER EndingByte,
01521 IN OUT PRTL_SPLAY_LINKS *LastEdgeNode,
01522 IN OUT PBOOLEAN GreaterThan
01523 )
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 {
01555
PLOCKTREE_NODE Node, LastOverlapNode;
01556 PRTL_SPLAY_LINKS SplayLinks;
01557
PSH_LOCK Lock;
01558
01559
if (LastEdgeNode) *LastEdgeNode =
NULL;
01560
if (
GreaterThan) *
GreaterThan =
FALSE;
01561
01562 LastOverlapNode =
NULL;
01563 SplayLinks = Tree;
01564
01565
while (SplayLinks) {
01566
01567 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
01568
01569
01570
01571
01572
01573
01574
Lock = CONTAINING_RECORD( Node->
Locks.Next,
SH_LOCK, Link );
01575
01576
01577
01578
01579
01580
01581
01582
01583
if (Node->
Extent < (ULONGLONG)StartingByte->QuadPart ||
01584 (
Lock->LockInfo.StartingByte.QuadPart == 0 &&
Lock->LockInfo.Length.QuadPart == 0)) {
01585
01586
if ((ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart &&
01587 (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) {
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
break;
01603 }
01604
01605
01606
01607
01608
01609
01610
if (LastEdgeNode) *LastEdgeNode = SplayLinks;
01611
if (
GreaterThan) *
GreaterThan =
FALSE;
01612
01613 SplayLinks = RtlRightChild(SplayLinks);
01614
continue;
01615 }
01616
01617
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)EndingByte->QuadPart) {
01618
01619
01620
01621
01622
01623
01624
01625
01626
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)StartingByte->QuadPart) {
01627
01628
01629
01630
01631
01632
01633
break;
01634 }
01635
01636
01637
01638
01639
01640
01641
01642 LastOverlapNode = Node;
01643 }
01644
01645
01646
01647
01648
01649
01650
01651
if (LastEdgeNode) *LastEdgeNode = SplayLinks;
01652
if (
GreaterThan) *
GreaterThan =
TRUE;
01653
01654 SplayLinks = RtlLeftChild(SplayLinks);
01655 }
01656
01657
if (SplayLinks ==
NULL) {
01658
01659
01660
01661
01662
01663
01664
01665
01666 Node = LastOverlapNode;
01667 }
01668
01669
if (Node ==
NULL) {
01670
01671
01672
01673
01674
01675
return NULL;
01676 }
01677
01678
01679
01680
01681
01682
return &Node->
Links;
01683 }
01684
01685
01686 PRTL_SPLAY_LINKS
01687 FsRtlFindFirstOverlappingExclusiveNode (
01688 IN PRTL_SPLAY_LINKS Tree,
01689 IN PLARGE_INTEGER StartingByte,
01690 IN PLARGE_INTEGER EndingByte,
01691 IN OUT PRTL_SPLAY_LINKS *LastEdgeNode,
01692 IN OUT PBOOLEAN GreaterThan
01693 )
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724 {
01725 PRTL_SPLAY_LINKS SplayLinks;
01726
PEX_LOCK Lock, LastOverlapNode;
01727
01728
if (LastEdgeNode) *LastEdgeNode =
NULL;
01729
if (
GreaterThan) *
GreaterThan =
FALSE;
01730
01731 LastOverlapNode =
NULL;
01732 SplayLinks = Tree;
01733
01734
while (SplayLinks) {
01735
01736
Lock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
01737
01738
01739
01740
01741
01742
01743
01744
01745
if ((ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart < (ULONGLONG)StartingByte->QuadPart ||
01746 (
Lock->LockInfo.StartingByte.QuadPart == 0 &&
Lock->LockInfo.Length.QuadPart == 0)) {
01747
01748
if ((ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart &&
01749 (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) {
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766 LastOverlapNode =
Lock;
01767
01768
if (LastEdgeNode) *LastEdgeNode = SplayLinks;
01769
if (
GreaterThan) *
GreaterThan =
FALSE;
01770
01771 SplayLinks = RtlLeftChild(SplayLinks);
01772
continue;
01773 }
01774
01775
01776
01777
01778
01779
01780
if (LastEdgeNode) *LastEdgeNode = SplayLinks;
01781
if (
GreaterThan) *
GreaterThan =
FALSE;
01782
01783 SplayLinks = RtlRightChild(SplayLinks);
01784
continue;
01785 }
01786
01787
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)EndingByte->QuadPart) {
01788
01789
01790
01791
01792
01793
01794
01795
01796
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart <= (ULONGLONG)StartingByte->QuadPart) {
01797
01798
01799
01800
01801
01802
01803
break;
01804 }
01805
01806
01807
01808
01809
01810
01811
01812 LastOverlapNode =
Lock;
01813 }
01814
01815
01816
01817
01818
01819
01820
if (LastEdgeNode) *LastEdgeNode = SplayLinks;
01821
if (
GreaterThan) *
GreaterThan =
TRUE;
01822
01823 SplayLinks = RtlLeftChild(SplayLinks);
01824 }
01825
01826
if (SplayLinks ==
NULL) {
01827
01828
01829
01830
01831
01832
01833
01834
01835
Lock = LastOverlapNode;
01836 }
01837
01838
if (
Lock ==
NULL) {
01839
01840
01841
01842
01843
01844
return NULL;
01845 }
01846
01847
01848
01849
01850
01851
return &
Lock->Links;
01852 }
01853
01854
01855
PSH_LOCK
01856 FsRtlFindFirstOverlapInNode (
01857 IN PLOCKTREE_NODE Node,
01858 IN PLARGE_INTEGER StartingByte,
01859 IN PLARGE_INTEGER EndingByte
01860 )
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 {
01885
PSH_LOCK Lock;
01886 PSINGLE_LIST_ENTRY Link;
01887
01888
for (Link = Node->Locks.Next;
01889 Link;
01890 Link = Link->Next) {
01891
01892
Lock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
01893
01894
01895
01896
01897
01898
01899
01900
if ((ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart < (ULONGLONG)StartingByte->QuadPart ||
01901 (
Lock->LockInfo.StartingByte.QuadPart == 0 &&
Lock->LockInfo.Length.QuadPart == 0)) {
01902
01903
01904
01905
01906
01907
01908
if ((ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart == (ULONGLONG)EndingByte->QuadPart &&
01909 (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)StartingByte->QuadPart) {
01910
01911
return Lock;
01912 }
01913
01914
01915
01916
01917
01918
continue;
01919 }
01920
01921
01922
01923
01924
01925
01926
01927
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)EndingByte->QuadPart) {
01928
01929
return NULL;
01930 }
01931
01932
01933
01934
01935
01936
return Lock;
01937 }
01938
01939
01940
01941
01942
01943
01944
ASSERT(
FALSE );
01945
01946
return NULL;
01947 }
01948
01949
01950
PFILE_LOCK_INFO
01951 FsRtlGetNextFileLock (
01952 IN
PFILE_LOCK FileLock,
01953 IN BOOLEAN Restart
01954 )
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996 {
01997
FILE_LOCK_INFO FileLockInfo;
01998 PVOID ContinuationPointer;
01999
PLOCK_INFO LockInfo;
02000
PLOCKTREE_NODE Node;
02001 PSINGLE_LIST_ENTRY Link;
02002 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks;
02003
PSH_LOCK ShLock;
02004
PEX_LOCK ExLock;
02005 BOOLEAN FoundReturnable,
GreaterThan;
02006 KIRQL OldIrql;
02007
02008
DebugTrace(+1,
Dbg,
"FsRtlGetNextFileLock, FileLock = %08lx\n", FileLock);
02009
02010
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
02011
02012
02013
02014
02015
return NULL;
02016 }
02017
02018 FoundReturnable =
FALSE;
02019
02020
02021
02022
02023
02024 FileLockInfo = FileLock->LastReturnedLockInfo;
02025 ContinuationPointer = FileLock->LastReturnedLock;
02026
02027
FsRtlAcquireLockQueue (&LockInfo->
LockQueue, &OldIrql);
02028
02029
if (!Restart) {
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
if (FileLockInfo.
ExclusiveLock) {
02045
02046
02047
02048
02049
02050 ExLock =
NULL;
02051
02052 SplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockInfo->
LockQueue.
ExclusiveLockTree,
02053 &FileLockInfo.
StartingByte,
02054 &FileLockInfo.
EndingByte,
02055 &LastSplayLinks,
02056 &
GreaterThan );
02057
02058
if (SplayLinks ==
NULL) {
02059
02060
02061
02062
02063
02064
if (
GreaterThan) {
02065
02066
02067
02068
02069
02070
02071 SplayLinks = LastSplayLinks;
02072
02073 }
else {
02074
02075
02076
02077
02078
02079
if (LastSplayLinks) {
02080
02081 SplayLinks =
RtlRealSuccessor(LastSplayLinks);
02082 }
02083 }
02084
02085 }
else {
02086
02087
02088
02089
02090
02091
for (;
02092 SplayLinks;
02093 SplayLinks =
RtlRealSuccessor(SplayLinks)) {
02094
02095 ExLock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
02096
02097
if (ContinuationPointer == ExLock &&
02098 (ULONGLONG)FileLockInfo.
StartingByte.QuadPart == (ULONGLONG)ExLock->
LockInfo.
StartingByte.QuadPart &&
02099 (ULONGLONG)FileLockInfo.
Length.QuadPart == (ULONGLONG)ExLock->
LockInfo.
Length.QuadPart &&
02100 FileLockInfo.
Key == ExLock->
LockInfo.
Key &&
02101 FileLockInfo.
FileObject == ExLock->
LockInfo.
FileObject &&
02102 FileLockInfo.
ProcessId == ExLock->
LockInfo.
ProcessId) {
02103
02104
02105
02106
02107
02108 SplayLinks =
RtlRealSuccessor(SplayLinks);
02109
02110
02111
02112
02113
02114
break;
02115 }
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
if (ExLock->
LockInfo.
Length.QuadPart != 0 || FileLockInfo.
Length.QuadPart != 0) {
02128
02129
break;
02130 }
02131
02132
02133
02134
02135 }
02136 }
02137
02138
02139
02140
02141
02142
if (SplayLinks ==
NULL) {
02143
02144
02145
02146
02147
02148 SplayLinks = LockInfo->
LockQueue.
SharedLockTree;
02149
02150
if (SplayLinks) {
02151
02152
while (RtlLeftChild(SplayLinks)) {
02153
02154 SplayLinks = RtlLeftChild(SplayLinks);
02155 }
02156
02157 Node = CONTAINING_RECORD(SplayLinks,
LOCKTREE_NODE, Links);
02158 ShLock = CONTAINING_RECORD(Node->
Locks.Next,
SH_LOCK, Link);
02159
02160 FileLockInfo = ShLock->
LockInfo;
02161 ContinuationPointer = ShLock;
02162 FoundReturnable =
TRUE;
02163 }
02164
02165 }
else {
02166
02167
02168
02169
02170
02171 ExLock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
02172
02173 FileLockInfo = ExLock->
LockInfo;
02174 ContinuationPointer = ExLock;
02175 FoundReturnable =
TRUE;
02176 }
02177
02178 }
else {
02179
02180
02181
02182
02183
02184 Node =
NULL;
02185
02186 SplayLinks =
FsRtlFindFirstOverlappingSharedNode( LockInfo->
LockQueue.
SharedLockTree,
02187 &FileLockInfo.
StartingByte,
02188 &FileLockInfo.
EndingByte,
02189 &LastSplayLinks,
02190 &
GreaterThan );
02191
02192
if (SplayLinks ==
NULL) {
02193
02194
02195
02196
02197
02198
if (
GreaterThan) {
02199
02200
02201
02202
02203
02204
02205
if (LastSplayLinks) {
02206
02207 SplayLinks = LastSplayLinks;
02208 Node = CONTAINING_RECORD( LastSplayLinks,
LOCKTREE_NODE, Links );
02209 }
02210
02211 }
else {
02212
02213
02214
02215
02216
02217
if (LastSplayLinks) {
02218
02219 SplayLinks =
RtlRealSuccessor(LastSplayLinks);
02220
02221
if (SplayLinks) {
02222
02223 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
02224 }
02225 }
02226 }
02227
02228 }
else {
02229
02230
02231
02232
02233
02234 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
02235 }
02236
02237
02238
02239
02240
02241
02242
if (Node !=
NULL) {
02243
02244
02245
02246
02247
02248
for (Link = Node->
Locks.Next;
02249 Link;
02250 Link = Link->Next) {
02251
02252
02253
02254
02255
02256 ShLock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
02257
02258
02259
02260
02261
02262
if (ContinuationPointer == ShLock &&
02263 (ULONGLONG)FileLockInfo.
StartingByte.QuadPart == (ULONGLONG)ShLock->
LockInfo.
StartingByte.QuadPart &&
02264 (ULONGLONG)FileLockInfo.
Length.QuadPart == (ULONGLONG)ShLock->
LockInfo.
Length.QuadPart &&
02265 FileLockInfo.
Key == ShLock->
LockInfo.
Key &&
02266 FileLockInfo.
FileObject == ShLock->
LockInfo.
FileObject &&
02267 FileLockInfo.
ProcessId == ShLock->
LockInfo.
ProcessId) {
02268
02269 Link = Link->Next;
02270
break;
02271 }
02272
02273
02274
02275
02276
02277
if ((ULONGLONG)FileLockInfo.
StartingByte.QuadPart < (ULONGLONG)ShLock->
LockInfo.
StartingByte.QuadPart) {
02278
02279
break;
02280 }
02281 }
02282
02283
if (Link ==
NULL) {
02284
02285
02286
02287
02288
02289
02290
02291
02292 SplayLinks =
RtlRealSuccessor(SplayLinks);
02293
02294
if (SplayLinks) {
02295
02296 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
02297
02298 Link = Node->
Locks.Next;
02299 }
02300 }
02301
02302
if (Link) {
02303
02304
02305
02306
02307
02308 ShLock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
02309
02310 FileLockInfo = ShLock->
LockInfo;
02311 ContinuationPointer = ShLock;
02312 FoundReturnable =
TRUE;
02313 }
02314
02315 }
02316 }
02317
02318 }
else {
02319
02320
02321
02322
02323
02324
02325
if (LockInfo->
LockQueue.
ExclusiveLockTree) {
02326
02327 SplayLinks = LockInfo->
LockQueue.
ExclusiveLockTree;
02328
02329
while (RtlLeftChild(SplayLinks) !=
NULL) {
02330
02331 SplayLinks = RtlLeftChild(SplayLinks);
02332 }
02333
02334 ExLock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
02335
02336 FileLockInfo = ExLock->
LockInfo;
02337 ContinuationPointer = ExLock;
02338 FoundReturnable =
TRUE;
02339
02340 }
else {
02341
02342
if (LockInfo->
LockQueue.
SharedLockTree) {
02343
02344 SplayLinks = LockInfo->
LockQueue.
SharedLockTree;
02345
02346
while (RtlLeftChild(SplayLinks) !=
NULL) {
02347
02348 SplayLinks = RtlLeftChild(SplayLinks);
02349 }
02350
02351 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
02352 ShLock = CONTAINING_RECORD( Node->
Locks.Next,
SH_LOCK, Link );
02353
02354 FileLockInfo = ShLock->
LockInfo;
02355 ContinuationPointer = ShLock;
02356 FoundReturnable =
TRUE;
02357 }
02358 }
02359 }
02360
02361
02362
02363
02364
02365
FsRtlReleaseLockQueue (&LockInfo->
LockQueue, OldIrql);
02366
02367
if (!FoundReturnable) {
02368
02369
02370
02371
02372
02373
return NULL;
02374 }
02375
02376
02377
02378
02379
02380 FileLock->LastReturnedLockInfo = FileLockInfo;
02381 FileLock->LastReturnedLock = ContinuationPointer;
02382
02383
02384
02385
02386
02387
return &FileLock->LastReturnedLockInfo;
02388 }
02389
02390
02391 BOOLEAN
02392 FsRtlCheckNoSharedConflict (
02393 IN PLOCK_QUEUE LockQueue,
02394 IN PLARGE_INTEGER Starting,
02395 IN PLARGE_INTEGER Ending
02396 )
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425 {
02426 PRTL_SPLAY_LINKS SplayLinks, BeginLinks;
02427
PLOCKTREE_NODE Node;
02428
02429 SplayLinks =
FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree,
02430 Starting,
02431 Ending,
02432 &BeginLinks,
02433
NULL);
02434
02435
if (BeginLinks) {
02436
02437 LockQueue->SharedLockTree =
RtlSplay(BeginLinks);
02438 }
02439
02440
02441
02442
02443
02444
if (SplayLinks) {
02445
02446 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
02447
02448
if (Node->
HoleyNode) {
02449
02450
return (BOOLEAN)(
FsRtlFindFirstOverlapInNode( Node, Starting, Ending ) ==
NULL);
02451 }
02452
02453
02454
02455
02456
02457
return FALSE;
02458 }
02459
02460
02461
02462
02463
02464
return TRUE;
02465 }
02466
02467
02468 BOOLEAN
02469 FsRtlCheckNoExclusiveConflict (
02470 IN PLOCK_QUEUE LockQueue,
02471 IN PLARGE_INTEGER Starting,
02472 IN PLARGE_INTEGER Ending,
02473 IN ULONG Key,
02474 IN
PFILE_OBJECT FileObject,
02475 IN PVOID ProcessId
02476 )
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505 {
02506 PRTL_SPLAY_LINKS SplayLinks, BeginLinks;
02507
PEX_LOCK Lock;
02508 BOOLEAN
Status =
TRUE;
02509
02510
02511
02512
02513
02514
for (SplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree,
02515 Starting,
02516 Ending,
02517 &BeginLinks,
02518
NULL);
02519 SplayLinks;
02520 SplayLinks =
RtlRealSuccessor(SplayLinks)) {
02521
02522
Lock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
02523
02524
02525
02526
02527
02528
02529
02530
02531
if ((ULONGLONG)Ending->QuadPart < (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart) {
02532
02533
DebugTrace(0,
Dbg,
"FsRtlCheckForExclusiveConflict, Ending < Lock->StartingByte\n", 0);
02534
02535
break;
02536 }
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
if ((ULONGLONG)Starting->QuadPart <= (ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart) {
02549
02550
02551
02552
02553
02554
02555
02556
if ((
Lock->LockInfo.FileObject != FileObject) ||
02557 (
Lock->LockInfo.ProcessId != ProcessId) ||
02558 (
Lock->LockInfo.Key !=
Key)) {
02559
02560
DebugTrace(0,
Dbg,
"FsRtlCheckForExclusiveConflict, Range locked already\n", 0);
02561
02562
Status =
FALSE;
02563
break;
02564 }
02565 }
02566 }
02567
02568
if (BeginLinks) {
02569
02570 LockQueue->ExclusiveLockTree =
RtlSplay(BeginLinks);
02571 }
02572
02573
02574
02575
02576
02577
return Status;
02578 }
02579
02580
02581 BOOLEAN
02582 FsRtlFastCheckLockForRead (
02583 IN
PFILE_LOCK FileLock,
02584 IN PLARGE_INTEGER StartingByte,
02585 IN PLARGE_INTEGER Length,
02586 IN ULONG Key,
02587 IN
PFILE_OBJECT FileObject,
02588 IN PVOID ProcessId
02589 )
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619 {
02620 LARGE_INTEGER Starting;
02621 LARGE_INTEGER Ending;
02622
02623
PLOCK_INFO LockInfo;
02624
PLOCK_QUEUE LockQueue;
02625 KIRQL OldIrql;
02626
PFILE_LOCK_INFO LastLock;
02627 BOOLEAN
Status;
02628
02629
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
02630
02631
02632
02633
02634
02635
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForRead, No lock info\n", 0);
02636
return TRUE;
02637 }
02638
02639
02640
02641
02642
02643
if (LockInfo->
LockQueue.
ExclusiveLockTree ==
NULL) {
02644
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForRead, No exlocks present\n", 0);
02645
return TRUE;
02646 }
02647
02648
02649
02650
02651
02652
if ((ULONGLONG)Length->QuadPart == 0) {
02653
02654
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForRead, Length == 0\n", 0);
02655
return TRUE;
02656 }
02657
02658
02659
02660
02661
02662 Starting = *StartingByte;
02663 (ULONGLONG)Ending.QuadPart = (ULONGLONG)Starting.QuadPart + (ULONGLONG)Length->QuadPart - 1;
02664
02665
02666
02667
02668
02669 LockQueue = &LockInfo->
LockQueue;
02670
02671
02672
02673
02674
02675
02676
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
02677
02678
02679
02680
02681
02682
if ( ((ULONGLONG)Ending.QuadPart < (ULONGLONG)LockInfo->
LowestLockOffset) ) {
02683
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForRead (below lowest lock)\n", 0);
02684
02685
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02686
return TRUE;
02687 }
02688
02689
02690
02691
02692
02693 LastLock = (
PFILE_LOCK_INFO)FileObject->LastLock;
02694
if ((LastLock !=
NULL) &&
02695 ((ULONGLONG)Starting.QuadPart >= (ULONGLONG)LastLock->
StartingByte.QuadPart) &&
02696 ((ULONGLONG)Ending.QuadPart <= (ULONGLONG)LastLock->
EndingByte.QuadPart) &&
02697 (LastLock->
Key ==
Key) &&
02698 (LastLock->
ProcessId == ProcessId)) {
02699
02700
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02701
return TRUE;
02702 }
02703
02704
02705
02706
02707
02708
02709
Status =
FsRtlCheckNoExclusiveConflict(LockQueue, &Starting, &Ending,
Key, FileObject, ProcessId);
02710
02711
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02712
02713
return Status;
02714 }
02715
02716
02717 BOOLEAN
02718 FsRtlFastCheckLockForWrite (
02719 IN
PFILE_LOCK FileLock,
02720 IN PLARGE_INTEGER StartingByte,
02721 IN PLARGE_INTEGER Length,
02722 IN ULONG Key,
02723 IN PVOID FileObject,
02724 IN PVOID ProcessId
02725 )
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755 {
02756 LARGE_INTEGER Starting;
02757 LARGE_INTEGER Ending;
02758
02759
PLOCK_INFO LockInfo;
02760
PLOCK_QUEUE LockQueue;
02761 KIRQL OldIrql;
02762
PFILE_LOCK_INFO LastLock;
02763 BOOLEAN
Status;
02764
02765
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
02766
02767
02768
02769
02770
02771
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForRead, No lock info\n", 0);
02772
return TRUE;
02773 }
02774
02775
02776
02777
02778
02779
if (LockInfo->
LockQueue.
SharedLockTree ==
NULL && LockInfo->
LockQueue.
ExclusiveLockTree ==
NULL) {
02780
02781
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForWrite, No locks present\n", 0);
02782
return TRUE;
02783 }
02784
02785
02786
02787
02788
02789
if ((ULONGLONG)Length->QuadPart == 0) {
02790
02791
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForWrite, Length == 0\n", 0);
02792
return TRUE;
02793 }
02794
02795
02796
02797
02798
02799 Starting = *StartingByte;
02800 (ULONGLONG)Ending.QuadPart = (ULONGLONG)Starting.QuadPart + (ULONGLONG)Length->QuadPart - 1;
02801
02802
02803
02804
02805
02806 LockQueue = &LockInfo->
LockQueue;
02807
02808
02809
02810
02811
02812
02813
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
02814
02815
02816
02817
02818
02819
if ( ((ULONGLONG)Ending.QuadPart < (ULONGLONG)LockInfo->
LowestLockOffset) ) {
02820
02821
DebugTrace(0,
Dbg,
"FsRtlFastCheckLockForWrite (below lowest lock)\n", 0);
02822
02823
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02824
return TRUE;
02825 }
02826
02827
02828
02829
02830
02831 LastLock = (
PFILE_LOCK_INFO)((
PFILE_OBJECT)FileObject)->LastLock;
02832
if ((LastLock !=
NULL) &&
02833 ((ULONGLONG)Starting.QuadPart >= (ULONGLONG)LastLock->
StartingByte.QuadPart) &&
02834 ((ULONGLONG)Ending.QuadPart <= (ULONGLONG)LastLock->
EndingByte.QuadPart) &&
02835 (LastLock->
Key ==
Key) &&
02836 (LastLock->
ProcessId == ProcessId) &&
02837 LastLock->
ExclusiveLock) {
02838
02839
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02840
return TRUE;
02841 }
02842
02843
02844
02845
02846
02847
Status =
FsRtlCheckNoSharedConflict(LockQueue, &Starting, &Ending);
02848
02849
if (
Status ==
TRUE) {
02850
02851
02852
02853
02854
02855
Status =
FsRtlCheckNoExclusiveConflict(LockQueue, &Starting, &Ending,
Key, FileObject, ProcessId);
02856 }
02857
02858
FsRtlReleaseLockQueue(LockQueue, OldIrql);
02859
02860
return Status;
02861 }
02862
02863
02864
VOID
02865 FsRtlSplitLocks (
02866 IN PLOCKTREE_NODE ParentNode,
02867 IN PSINGLE_LIST_ENTRY *pStartLink OPTIONAL,
02868 IN PLARGE_INTEGER LastShadowedByte OPTIONAL,
02869 IN PLARGE_INTEGER GlueOffset OPTIONAL
02870 )
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900 {
02901
PSH_LOCK Lock;
02902
PLOCKTREE_NODE NewNode;
02903 PSINGLE_LIST_ENTRY Link, *pLink, *NextpLink;
02904 LARGE_INTEGER MaxOffset, StartOffset, HaltOffset;
02905
02906 BOOLEAN ExtentValid;
02907 BOOLEAN FailedHoleySplit =
FALSE;
02908
02909
02910
02911
02912
02913
02914
02915
if (ParentNode->HoleyNode) {
02916
02917
02918
02919
02920
02921
02922
02923 pStartLink = &ParentNode->Locks.Next;
02924 ParentNode->HoleyNode =
FALSE;
02925
02926 HaltOffset.QuadPart = ParentNode->Extent;
02927
02928 }
else {
02929
02930 HaltOffset = *LastShadowedByte;
02931 MaxOffset = *GlueOffset;
02932 StartOffset.QuadPart = 0;
02933
02934
if (!ParentNode->Locks.Next ||
02935 (ULONGLONG)HaltOffset.QuadPart <= (ULONGLONG)MaxOffset.QuadPart) {
02936
02937
02938
02939
02940
02941
02942
02943
02944
return;
02945 }
02946 }
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957 ExtentValid = (ParentNode->Extent > (ULONGLONG)HaltOffset.QuadPart);
02958
02959
for (pLink = pStartLink;
02960 (Link = *pLink) !=
NULL;
02961 pLink = NextpLink) {
02962
02963 NextpLink = &Link->Next;
02964
02965
Lock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
02966
02967
if (ParentNode->Locks.Next == *pLink) {
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977 MaxOffset.QuadPart =
Lock->LockInfo.EndingByte.QuadPart;
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 StartOffset.QuadPart =
Lock->LockInfo.StartingByte.QuadPart;
02988
02989
02990
02991
02992
02993
02994
if (!ExtentValid) {
02995
02996 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart;
02997 }
02998
02999
continue;
03000 }
03001
03002
03003
03004
03005
03006
03007
03008
03009
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)MaxOffset.QuadPart &&
03010 !(
Lock->LockInfo.Length.QuadPart == 0 &&
03011
Lock->LockInfo.StartingByte.QuadPart == StartOffset.QuadPart)) {
03012
03013
03014
03015
03016
03017 NewNode =
FsRtlAllocateLockTreeNode();
03018
03019
if (NewNode ==
NULL) {
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
if (ParentNode->HoleyNode) {
03035
03036 FailedHoleySplit =
TRUE;
03037 }
03038
03039 ParentNode->HoleyNode =
TRUE;
03040
03041 }
else {
03042
03043
03044
03045
03046
03047 RtlInitializeSplayLinks(&NewNode->
Links);
03048 NewNode->
HoleyNode =
FALSE;
03049
03050
03051
03052
03053
03054
03055
03056
03057
if (RtlRightChild(&ParentNode->Links) ==
NULL) {
03058
03059 RtlInsertAsRightChild(&ParentNode->Links, &NewNode->
Links);
03060
03061 }
else {
03062
03063
ASSERT(RtlLeftChild(
RtlRealSuccessor(&ParentNode->Links)) ==
NULL);
03064 RtlInsertAsLeftChild(
RtlRealSuccessor(&ParentNode->Links), &NewNode->
Links);
03065 }
03066
03067
03068
03069
03070
03071 NewNode->
Locks.Next = *pLink;
03072 *pLink =
NULL;
03073
03074 NewNode->
Tail.Next = ParentNode->Tail.Next;
03075 ParentNode->Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next );
03076
03077
03078
03079
03080
03081 NextpLink = &NewNode->
Locks.Next;
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091 NewNode->
Extent = ParentNode->Extent;
03092 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart;
03093
03094
03095
03096
03097
03098
if (!FailedHoleySplit) {
03099
03100 ParentNode->HoleyNode =
FALSE;
03101
03102 }
else {
03103
03104
03105
03106
03107
03108 FailedHoleySplit =
FALSE;
03109 }
03110
03111
03112
03113
03114
03115 ParentNode = NewNode;
03116
03117
continue;
03118 }
03119 }
03120
03121
if (ExtentValid &&
03122 (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)HaltOffset.QuadPart) {
03123
03124
03125
03126
03127
03128
return;
03129 }
03130
03131
if ((ULONGLONG)MaxOffset.QuadPart < (ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart) {
03132
03133
03134
03135
03136
03137 MaxOffset.QuadPart =
Lock->LockInfo.EndingByte.QuadPart;
03138
03139
if (!ExtentValid) {
03140
03141
03142
03143
03144
03145 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart;
03146 }
03147 }
03148 }
03149
03150
03151
03152
03153
03154
03155 ParentNode->Extent = (ULONGLONG)MaxOffset.QuadPart;
03156
03157
return;
03158 }
03159
03160
03161
VOID
03162 FsRtlPrivateRemoveLock (
03163 IN PLOCK_INFO LockInfo,
03164 IN
PFILE_LOCK_INFO FileLockInfo,
03165 IN BOOLEAN CheckForWaiters
03166 )
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192 {
03193
NTSTATUS Status;
03194
03195
if (FileLockInfo->ExclusiveLock) {
03196
03197
03198
03199
03200
03201
Status =
FsRtlFastUnlockSingleExclusive( LockInfo,
03202
03203 FileLockInfo->FileObject,
03204 &FileLockInfo->StartingByte,
03205 &FileLockInfo->Length,
03206 FileLockInfo->ProcessId,
03207 FileLockInfo->Key,
03208
03209
NULL,
03210
TRUE,
03211 CheckForWaiters );
03212
03213
ASSERT(
Status == STATUS_SUCCESS);
03214
03215 }
else {
03216
03217
03218
03219
03220
03221
Status =
FsRtlFastUnlockSingleShared( LockInfo,
03222
03223 FileLockInfo->FileObject,
03224 &FileLockInfo->StartingByte,
03225 &FileLockInfo->Length,
03226 FileLockInfo->ProcessId,
03227 FileLockInfo->Key,
03228
03229
NULL,
03230
TRUE,
03231 CheckForWaiters );
03232
03233
ASSERT(
Status == STATUS_SUCCESS);
03234 }
03235
03236
return;
03237 }
03238
03239
03240
NTSTATUS
03241 FsRtlFastUnlockSingle (
03242 IN
PFILE_LOCK FileLock,
03243 IN
PFILE_OBJECT FileObject,
03244 IN LARGE_INTEGER UNALIGNED *FileOffset,
03245 IN PLARGE_INTEGER Length,
03246 IN
PEPROCESS ProcessId,
03247 IN ULONG Key,
03248 IN PVOID Context OPTIONAL,
03249 IN BOOLEAN AlreadySynchronized
03250 )
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286 {
03287
NTSTATUS Status;
03288
03289
03290
03291
03292
03293
03294
if (FileLock->LockInformation ==
NULL) {
03295
03296
03297
03298
03299
03300
return STATUS_RANGE_NOT_LOCKED;
03301 }
03302
03303
Status =
FsRtlFastUnlockSingleExclusive( FileLock->LockInformation,
03304 FileObject,
03305 FileOffset,
03306 Length,
03307 ProcessId,
03308
Key,
03309 Context,
03310
FALSE,
03311
TRUE );
03312
03313
if (
Status == STATUS_SUCCESS) {
03314
03315
03316
03317
03318
03319
return Status;
03320 }
03321
03322
Status =
FsRtlFastUnlockSingleShared( FileLock->LockInformation,
03323 FileObject,
03324 FileOffset,
03325 Length,
03326 ProcessId,
03327
Key,
03328 Context,
03329
FALSE,
03330
TRUE );
03331
03332
return Status;
03333 }
03334
03335
03336
NTSTATUS
03337 FsRtlFastUnlockSingleShared (
03338 IN PLOCK_INFO LockInfo,
03339 IN
PFILE_OBJECT FileObject,
03340 IN LARGE_INTEGER UNALIGNED *FileOffset,
03341 IN PLARGE_INTEGER Length,
03342 IN
PEPROCESS ProcessId,
03343 IN ULONG Key,
03344 IN PVOID Context OPTIONAL,
03345 IN BOOLEAN IgnoreUnlockRoutine,
03346 IN BOOLEAN CheckForWaiters
03347 )
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386 {
03387 PSINGLE_LIST_ENTRY *pLink, Link;
03388 KIRQL OldIrql;
03389
03390
PLOCK_QUEUE LockQueue;
03391 PRTL_SPLAY_LINKS SplayLinks;
03392 LARGE_INTEGER EndingOffset, MaxOffset;
03393
PLOCKTREE_NODE Node;
03394 LARGE_INTEGER AlignedFileOffset;
03395
03396
03397
03398
03399
03400 AlignedFileOffset = *FileOffset;
03401
03402 LockQueue = &LockInfo->LockQueue;
03403
03404
FsRtlAcquireLockQueue(LockQueue, &OldIrql);
03405
03406
03407
03408
03409
03410
if (LockQueue->
SharedLockTree ==
NULL) {
03411
03412
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03413
03414
return STATUS_RANGE_NOT_LOCKED;
03415 }
03416
03417
03418
03419
03420
03421
03422
03423 EndingOffset.QuadPart = (ULONGLONG)AlignedFileOffset.QuadPart + (ULONGLONG)Length->QuadPart - 1;
03424
03425 SplayLinks =
FsRtlFindFirstOverlappingSharedNode( LockQueue->
SharedLockTree,
03426 &AlignedFileOffset,
03427 &EndingOffset,
03428
NULL,
03429
NULL );
03430
03431
if (SplayLinks ==
NULL) {
03432
03433
03434
03435
03436
03437
FsRtlReleaseLockQueue(LockQueue, OldIrql);
03438
03439
return STATUS_RANGE_NOT_LOCKED;
03440 }
03441
03442 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
03443 MaxOffset.QuadPart = 0;
03444
03445
for (pLink = &Node->
Locks.Next;
03446 (Link = *pLink) !=
NULL;
03447 pLink = &Link->Next) {
03448
03449
PSH_LOCK Lock;
03450
03451
Lock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
03452
03453
DebugTrace(0,
Dbg,
"Sh Top of Loop, Lock = %08lx\n",
Lock );
03454
03455
if ((
Lock->LockInfo.FileObject == FileObject) &&
03456 (
Lock->LockInfo.ProcessId == ProcessId) &&
03457 (
Lock->LockInfo.Key ==
Key) &&
03458 ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)AlignedFileOffset.QuadPart) &&
03459 ((ULONGLONG)
Lock->LockInfo.Length.QuadPart == (ULONGLONG)Length->QuadPart)) {
03460
03461
DebugTrace(0,
Dbg,
"Sh Found one to unlock\n", 0);
03462
03463
03464
03465
03466
03467
03468
03469
if (FileObject->LastLock == &
Lock->LockInfo) {
03470
03471 FileObject->LastLock =
NULL;
03472 }
03473
03474
if (*pLink == Node->
Tail.Next) {
03475
03476
03477
03478
03479
03480
03481
03482 Node->
Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next );
03483 }
03484
03485
03486
03487
03488
03489 *pLink = Link->Next;
03490
03491
if (pLink == &Node->
Locks.Next) {
03492
03493
03494
03495
03496
03497
if (Node->
Locks.Next ==
NULL) {
03498
03499
03500
03501
03502
03503 LockQueue->
SharedLockTree =
RtlDelete(SplayLinks);
03504
03505
FsRtlFreeLockTreeNode(Node);
03506
03507 Node =
NULL;
03508 }
03509
03510
if (LockInfo->LowestLockOffset != 0xffffffff &&
03511 LockInfo->LowestLockOffset ==
Lock->LockInfo.StartingByte.LowPart) {
03512
03513
03514
03515
03516
03517
FsRtlPrivateResetLowestLockOffset(LockInfo);
03518 }
03519 }
03520
03521
03522
03523
03524
03525
03526
03527
if (Node) {
03528
03529
FsRtlSplitLocks(Node, pLink, &
Lock->LockInfo.EndingByte, &MaxOffset);
03530 }
03531
03532
if (!IgnoreUnlockRoutine && LockInfo->UnlockRoutine !=
NULL) {
03533
03534
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03535
03536 LockInfo->UnlockRoutine( Context, &
Lock->LockInfo );
03537
03538
FsRtlReacquireLockQueue( LockInfo, LockQueue, &OldIrql );
03539
03540 }
03541
03542
FsRtlFreeSharedLock(
Lock );
03543
03544
03545
03546
03547
03548
03549
if (CheckForWaiters && LockQueue->
WaitingLocks.Next) {
03550
03551
FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql );
03552 }
03553
03554
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03555
03556
return STATUS_SUCCESS;
03557 }
03558
03559
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)AlignedFileOffset.QuadPart) {
03560
03561
03562
03563
03564
03565
03566
break;
03567 }
03568
03569
if ((ULONGLONG)MaxOffset.QuadPart < (ULONGLONG)
Lock->LockInfo.EndingByte.QuadPart) {
03570
03571
03572
03573
03574
03575 MaxOffset.QuadPart =
Lock->LockInfo.EndingByte.QuadPart;
03576 }
03577 }
03578
03579
03580
03581
03582
03583
FsRtlReleaseLockQueue(LockQueue, OldIrql);
03584
return STATUS_RANGE_NOT_LOCKED;
03585 }
03586
03587
03588
NTSTATUS
03589 FsRtlFastUnlockSingleExclusive (
03590 IN PLOCK_INFO LockInfo,
03591 IN
PFILE_OBJECT FileObject,
03592 IN LARGE_INTEGER UNALIGNED *FileOffset,
03593 IN PLARGE_INTEGER Length,
03594 IN
PEPROCESS ProcessId,
03595 IN ULONG Key,
03596 IN PVOID Context OPTIONAL,
03597 IN BOOLEAN IgnoreUnlockRoutine,
03598 IN BOOLEAN CheckForWaiters
03599 )
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638 {
03639 KIRQL OldIrql;
03640
PLOCK_QUEUE LockQueue;
03641 PRTL_SPLAY_LINKS SplayLinks;
03642 LARGE_INTEGER EndingOffset;
03643
PEX_LOCK Lock;
03644 LARGE_INTEGER AlignedFileOffset;
03645
03646
03647
03648
03649
03650 AlignedFileOffset = *FileOffset;
03651
03652 LockQueue = &LockInfo->LockQueue;
03653
03654
FsRtlAcquireLockQueue(LockQueue, &OldIrql);
03655
03656
03657
03658
03659
03660
if (LockQueue->
ExclusiveLockTree ==
NULL) {
03661
03662
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03663
03664
return STATUS_RANGE_NOT_LOCKED;
03665 }
03666
03667
03668
03669
03670
03671
03672
03673
03674 EndingOffset.QuadPart = (ULONGLONG)AlignedFileOffset.QuadPart + (ULONGLONG)Length->QuadPart - 1;
03675
03676
for (SplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockQueue->
ExclusiveLockTree,
03677 &AlignedFileOffset,
03678 &EndingOffset,
03679
NULL,
03680
NULL );
03681 SplayLinks;
03682 SplayLinks =
RtlRealSuccessor(SplayLinks)) {
03683
03684
Lock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
03685
03686
if ((
Lock->LockInfo.FileObject == FileObject) &&
03687 (
Lock->LockInfo.ProcessId == ProcessId) &&
03688 (
Lock->LockInfo.Key ==
Key) &&
03689 ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart == (ULONGLONG)AlignedFileOffset.QuadPart) &&
03690 ((ULONGLONG)
Lock->LockInfo.Length.QuadPart == (ULONGLONG)Length->QuadPart)) {
03691
03692
DebugTrace(0,
Dbg,
"Ex Found one to unlock\n", 0);
03693
03694
03695
03696
03697
03698
03699
03700
if (FileObject->LastLock == &
Lock->LockInfo) {
03701
03702 FileObject->LastLock =
NULL;
03703 }
03704
03705
03706
03707
03708
03709 LockQueue->
ExclusiveLockTree =
RtlDelete(&
Lock->Links);
03710
03711
if (LockInfo->LowestLockOffset != 0xffffffff &&
03712 LockInfo->LowestLockOffset ==
Lock->LockInfo.StartingByte.LowPart) {
03713
03714
03715
03716
03717
03718
03719
FsRtlPrivateResetLowestLockOffset(LockInfo);
03720 }
03721
03722
if (!IgnoreUnlockRoutine && LockInfo->UnlockRoutine !=
NULL) {
03723
03724
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03725
03726 LockInfo->UnlockRoutine( Context, &
Lock->LockInfo );
03727
03728
FsRtlReacquireLockQueue( LockInfo, LockQueue, &OldIrql );
03729
03730 }
03731
03732
FsRtlFreeExclusiveLock(
Lock );
03733
03734
03735
03736
03737
03738
03739
if (CheckForWaiters && LockQueue->
WaitingLocks.Next) {
03740
03741
FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql );
03742 }
03743
03744
FsRtlReleaseLockQueue( LockQueue, OldIrql );
03745
03746
return STATUS_SUCCESS;
03747 }
03748
03749
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)AlignedFileOffset.QuadPart) {
03750
03751
03752
03753
03754
03755
03756
break;
03757 }
03758 }
03759
03760
03761
03762
03763
03764
FsRtlReleaseLockQueue(LockQueue, OldIrql);
03765
return STATUS_RANGE_NOT_LOCKED;
03766 }
03767
03768
03769
NTSTATUS
03770 FsRtlFastUnlockAll (
03771 IN
PFILE_LOCK FileLock,
03772 IN
PFILE_OBJECT FileObject,
03773 IN
PEPROCESS ProcessId,
03774 IN PVOID Context OPTIONAL
03775 )
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803 {
03804
return FsRtlPrivateFastUnlockAll(
03805 FileLock,
03806 FileObject,
03807 ProcessId,
03808 0,
FALSE,
03809 Context );
03810 }
03811
03812
03813
NTSTATUS
03814 FsRtlFastUnlockAllByKey (
03815 IN
PFILE_LOCK FileLock,
03816 IN
PFILE_OBJECT FileObject,
03817 IN
PEPROCESS ProcessId,
03818 IN ULONG Key,
03819 IN PVOID Context OPTIONAL
03820 )
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851 {
03852
return FsRtlPrivateFastUnlockAll(
03853 FileLock,
03854 FileObject,
03855 ProcessId,
03856
Key,
TRUE,
03857 Context );
03858
03859 }
03860
03861
03862
03863
03864
03865
03866 BOOLEAN
03867 FsRtlPrivateLock (
03868 IN
PFILE_LOCK FileLock,
03869 IN
PFILE_OBJECT FileObject,
03870 IN PLARGE_INTEGER FileOffset,
03871 IN PLARGE_INTEGER Length,
03872 IN
PEPROCESS ProcessId,
03873 IN ULONG Key,
03874 IN BOOLEAN FailImmediately,
03875 IN BOOLEAN ExclusiveLock,
03876 OUT PIO_STATUS_BLOCK Iosb,
03877 IN
PIRP Irp OPTIONAL,
03878 IN PVOID Context,
03879 IN BOOLEAN AlreadySynchronized
03880 )
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925 {
03926 BOOLEAN Results;
03927 BOOLEAN AccessGranted;
03928 BOOLEAN ViaFastCall;
03929 BOOLEAN ReleaseQueue =
FALSE;
03930
03931
PLOCK_INFO LockInfo;
03932
PLOCK_QUEUE LockQueue;
03933 KIRQL OldIrql;
03934
FILE_LOCK_INFO FileLockInfo;
03935
03936
DebugTrace(+1,
Dbg,
"FsRtlPrivateLock, FileLock = %08lx\n", FileLock);
03937
03938
03939
03940
03941
03942 ViaFastCall = (BOOLEAN) !ARGUMENT_PRESENT(
Irp );
03943
03944
if ((LockInfo = (
PLOCK_INFO) FileLock->LockInformation) ==
NULL) {
03945
DebugTrace(+2,
Dbg,
"FsRtlPrivateLock, New LockInfo required\n", 0);
03946
03947
03948
03949
03950
03951
03952
if (!
FsRtlPrivateInitializeFileLock (FileLock, ViaFastCall)) {
03953
03954
return FALSE;
03955 }
03956
03957
03958
03959
03960
03961
03962 FileLock->FastIoIsQuestionable =
TRUE;
03963
03964
03965
03966
03967
03968 LockInfo = (
PLOCK_INFO) FileLock->LockInformation;
03969 }
03970
03971
03972
03973
03974
03975
03976 FileLockInfo.
StartingByte = *FileOffset;
03977 FileLockInfo.
Length = *Length;
03978 (ULONGLONG)FileLockInfo.
EndingByte.QuadPart =
03979 (ULONGLONG)FileLockInfo.
StartingByte.QuadPart + (ULONGLONG)FileLockInfo.
Length.QuadPart - 1;
03980
03981 FileLockInfo.
Key =
Key;
03982 FileLockInfo.
FileObject = FileObject;
03983 FileLockInfo.
ProcessId = ProcessId;
03984 FileLockInfo.
ExclusiveLock = ExclusiveLock;
03985
03986 LockQueue = &LockInfo->
LockQueue;
03987
03988
03989
03990
03991
03992
FsRtlAcquireLockQueue(LockQueue, &OldIrql);
03993 ReleaseQueue =
TRUE;
03994
03995
try {
03996
03997
03998
03999
04000
04001
04002
if (ExclusiveLock) {
04003
04004
DebugTrace(0,
Dbg,
"Check for write access\n", 0);
04005
04006 AccessGranted =
FsRtlPrivateCheckForExclusiveLockAccess(
04007 LockQueue,
04008 &FileLockInfo );
04009
04010 }
else {
04011
04012
DebugTrace(0,
Dbg,
"Check for read access\n", 0);
04013
04014 AccessGranted =
FsRtlPrivateCheckForSharedLockAccess(
04015 LockQueue,
04016 &FileLockInfo );
04017 }
04018
04019
04020
04021
04022
04023
04024
if (!AccessGranted) {
04025
04026
DebugTrace(0,
Dbg,
"We do not have access\n", 0);
04027
04028
04029
04030
04031
04032
04033
04034
04035
if (FailImmediately) {
04036
04037
04038
04039
04040
04041
04042
DebugTrace(0,
Dbg,
"And we fail immediately\n", 0);
04043
04044 Iosb->Status = STATUS_LOCK_NOT_GRANTED;
04045
try_return( Results =
TRUE );
04046
04047 }
else if (ARGUMENT_PRESENT(
Irp)) {
04048
04049
PWAITING_LOCK WaitingLock;
04050
04051
DebugTrace(0,
Dbg,
"And we enqueue the Irp for later\n", 0);
04052
04053
04054
04055
04056
04057
04058
04059 WaitingLock =
FsRtlAllocateWaitingLock();
04060
04061
04062
04063
04064
04065
if (WaitingLock ==
NULL) {
04066
04067
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
04068 }
04069
04070 WaitingLock->
Irp =
Irp;
04071 WaitingLock->
Context = Context;
04072
IoMarkIrpPending(
Irp );
04073
04074
04075
04076
04077
04078 WaitingLock->
Link.Next =
NULL;
04079
if (LockQueue->
WaitingLocks.Next ==
NULL) {
04080
04081
04082
04083
04084
04085 LockQueue->
WaitingLocks.Next = &WaitingLock->
Link;
04086 LockQueue->
WaitingLocksTail.Next = &WaitingLock->
Link;
04087
04088 }
else {
04089
04090
04091
04092
04093
04094 LockQueue->
WaitingLocksTail.Next->Next = &WaitingLock->
Link;
04095 LockQueue->
WaitingLocksTail.Next = &WaitingLock->
Link;
04096 }
04097
04098
04099
04100
04101
04102
04103
04104
Irp->
IoStatus.Information = (ULONG_PTR)LockInfo;
04105
IoSetCancelRoutine(
Irp,
FsRtlPrivateCancelFileLockIrp );
04106
04107
if (
Irp->
Cancel) {
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
if (
IoSetCancelRoutine(
Irp,
NULL )) {
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
Irp->
CancelIrql = OldIrql;
04132
FsRtlPrivateCancelFileLockIrp(
NULL,
Irp );
04133 ReleaseQueue =
FALSE;
04134 }
04135 }
04136
04137 Iosb->Status = STATUS_PENDING;
04138
try_return( Results =
TRUE );
04139
04140 }
else {
04141
04142
try_return( Results =
FALSE );
04143 }
04144 }
04145
04146
DebugTrace(0,
Dbg,
"We have access\n", 0);
04147
04148
if (!
FsRtlPrivateInsertLock( LockInfo, FileObject, &FileLockInfo )) {
04149
04150
04151
04152
04153
04154
04155
04156
if (ViaFastCall) {
04157
04158
try_return( Results =
FALSE );
04159
04160 }
else {
04161
04162
ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
04163 }
04164
04165 }
else {
04166
04167 Iosb->Status = STATUS_SUCCESS;
04168 }
04169
04170
04171
04172
04173
04174 Results =
TRUE;
04175
04176 try_exit: NOTHING;
04177 } finally {
04178
04179
if (ReleaseQueue) {
04180
04181
FsRtlReleaseLockQueue(LockQueue, OldIrql);
04182 }
04183
04184
04185
04186
04187
04188
if (!AbnormalTermination() && ARGUMENT_PRESENT(
Irp) && (Iosb->Status != STATUS_PENDING)) {
04189
04190
NTSTATUS NewStatus;
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
ObReferenceObject( FileObject );
04201
04202
04203
04204
04205
04206
04207
04208
FsRtlCompleteLockIrp(
04209 LockInfo,
04210 Context,
04211
Irp,
04212 Iosb->Status,
04213 &NewStatus,
04214 FileObject );
04215
04216
if (!
NT_SUCCESS(NewStatus) &&
NT_SUCCESS(Iosb->Status) ) {
04217
04218
04219
04220
04221
04222
FsRtlPrivateRemoveLock (
04223 LockInfo,
04224 &FileLockInfo,
04225
TRUE );
04226 }
04227
04228
04229
04230
04231
04232
ObDereferenceObject( FileObject );
04233
04234 Iosb->Status = NewStatus;
04235 }
04236
04237
DebugTrace(-1,
Dbg,
"FsRtlPrivateLock -> %08lx\n", Results);
04238 }
04239
04240
04241
04242
04243
04244
return Results;
04245 }
04246
04247
04248
04249
04250
04251
04252 BOOLEAN
04253 FsRtlPrivateInsertLock (
04254 IN PLOCK_INFO LockInfo,
04255 IN
PFILE_OBJECT FileObject,
04256 IN
PFILE_LOCK_INFO FileLockInfo
04257 )
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281 {
04282
04283
04284
04285
04286
if (FileLockInfo->ExclusiveLock) {
04287
04288
PEX_LOCK ExLock;
04289
04290 ExLock =
FsRtlAllocateExclusiveLock();
04291
04292
if (ExLock ==
NULL) {
04293
04294
return FALSE;
04295 }
04296
04297 ExLock->
LockInfo = *FileLockInfo;
04298
04299
FsRtlPrivateInsertExclusiveLock( &LockInfo->LockQueue, ExLock );
04300
04301 FileObject->LastLock = &ExLock->
LockInfo;
04302
04303 }
else {
04304
04305
PSH_LOCK ShLock;
04306
04307 ShLock =
FsRtlAllocateSharedLock();
04308
04309
if (ShLock ==
NULL) {
04310
04311
return FALSE;
04312 }
04313
04314 ShLock->
LockInfo = *FileLockInfo;
04315
04316
if (!
FsRtlPrivateInsertSharedLock( &LockInfo->LockQueue, ShLock )) {
04317
04318
return FALSE;
04319 }
04320
04321 FileObject->LastLock = &ShLock->
LockInfo;
04322 }
04323
04324
04325
04326
04327
04328
if ((ULONGLONG)FileLockInfo->StartingByte.QuadPart < (ULONGLONG)LockInfo->LowestLockOffset) {
04329
04330
ASSERT( FileLockInfo->StartingByte.HighPart == 0 );
04331 LockInfo->LowestLockOffset = FileLockInfo->StartingByte.LowPart;
04332 }
04333
04334
return TRUE;
04335 }
04336
04337
04338
04339
04340
04341
04342 BOOLEAN
04343 FsRtlPrivateInsertSharedLock (
04344 IN PLOCK_QUEUE LockQueue,
04345 IN PSH_LOCK NewLock
04346 )
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367 {
04368 PSINGLE_LIST_ENTRY pLink, Link;
04369 PRTL_SPLAY_LINKS OverlappedSplayLinks, ParentSplayLinks;
04370
PLOCKTREE_NODE Node, NextNode;
04371
PSH_LOCK NextLock;
04372 BOOLEAN
GreaterThan;
04373
04374 OverlappedSplayLinks =
FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree,
04375 &NewLock->LockInfo.StartingByte,
04376 &NewLock->LockInfo.EndingByte,
04377 &ParentSplayLinks,
04378 &
GreaterThan );
04379
04380
if (OverlappedSplayLinks ==
NULL) {
04381
04382
04383
04384
04385
04386 NextNode =
FsRtlAllocateLockTreeNode();
04387
04388
04389
04390
04391
04392
if (NextNode ==
NULL) {
04393
04394
return FALSE;
04395 }
04396
04397 RtlInitializeSplayLinks(&NextNode->
Links);
04398 NextNode->
HoleyNode =
FALSE;
04399
04400 NextNode->
Locks.Next = NextNode->
Tail.Next = &NewLock->Link;
04401 NextNode->
Extent = (ULONGLONG)NewLock->LockInfo.EndingByte.QuadPart;
04402 NewLock->Link.Next =
NULL;
04403
04404
if (ParentSplayLinks) {
04405
04406
04407
04408
04409
04410
if (
GreaterThan) {
04411
04412
ASSERT(RtlLeftChild(ParentSplayLinks) ==
NULL);
04413 RtlInsertAsLeftChild(ParentSplayLinks, &NextNode->
Links);
04414
04415 }
else {
04416
04417
ASSERT(RtlRightChild(ParentSplayLinks) ==
NULL);
04418 RtlInsertAsRightChild(ParentSplayLinks, &NextNode->
Links);
04419 }
04420
04421
04422
04423
04424
04425 LockQueue->SharedLockTree =
RtlSplay(&NextNode->
Links);
04426
04427 }
else {
04428
04429
04430
04431
04432
04433 LockQueue->SharedLockTree = &NextNode->
Links;
04434 }
04435
04436
return TRUE;
04437 }
04438
04439
04440
04441
04442
04443
04444 Node = CONTAINING_RECORD( OverlappedSplayLinks,
LOCKTREE_NODE, Links );
04445
04446
04447
04448
04449
04450
for (pLink = &Node->
Locks;
04451 (Link = pLink->Next) !=
NULL;
04452 pLink = Link) {
04453
04454
PSH_LOCK Lock;
04455
04456
Lock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
if (((ULONGLONG)NewLock->LockInfo.StartingByte.QuadPart < (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart) ||
04467
04468 ((ULONGLONG)NewLock->LockInfo.StartingByte.QuadPart == (ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart &&
04469 (NewLock->LockInfo.Length.QuadPart == 0 ||
Lock->LockInfo.Length.QuadPart != 0))) {
04470
04471
break;
04472 }
04473 }
04474
04475
04476
04477
04478
04479
04480
04481
DebugTrace(0,
Dbg,
"InsertSharedLock, Insert Before = %08lx\n", Link);
04482
04483
if (pLink->Next ==
NULL) {
04484
04485
04486
04487
04488
04489 Node->
Tail.Next = &NewLock->Link;
04490 }
04491
04492 NewLock->Link.Next = pLink->Next;
04493 pLink->Next = &NewLock->Link;
04494
04495
04496
04497
04498
04499 LockQueue->SharedLockTree =
RtlSplay(OverlappedSplayLinks);
04500
04501
if ((ULONGLONG)NewLock->LockInfo.EndingByte.QuadPart > Node->
Extent) {
04502
04503
04504
04505
04506
04507 Node->
Extent = NewLock->LockInfo.EndingByte.QuadPart;
04508
04509
04510
04511
04512
04513
04514
04515
04516 ParentSplayLinks = OverlappedSplayLinks;
04517
04518
for (OverlappedSplayLinks =
RtlRealSuccessor(ParentSplayLinks);
04519 OverlappedSplayLinks;
04520 OverlappedSplayLinks =
RtlRealSuccessor(ParentSplayLinks)) {
04521
04522 NextNode = CONTAINING_RECORD( OverlappedSplayLinks,
LOCKTREE_NODE, Links );
04523 NextLock = CONTAINING_RECORD( NextNode->
Locks.Next,
SH_LOCK, Link );
04524
04525
if ((ULONGLONG)NextLock->
LockInfo.
StartingByte.QuadPart > Node->
Extent) {
04526
04527
04528
04529
04530
04531
break;
04532 }
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
if (!Node->
HoleyNode && NextNode->
HoleyNode) {
04543
04544
FsRtlSplitLocks( NextNode,
NULL,
NULL,
NULL );
04545 }
04546
04547
04548
04549
04550
04551 Node->
Tail.Next->Next = NextNode->
Locks.Next;
04552 Node->
Tail.Next = NextNode->
Tail.Next;
04553
04554
if (NextNode->
Extent > Node->
Extent) {
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
if (NextNode->
HoleyNode) {
04566
04567 Node->
HoleyNode =
TRUE;
04568 }
04569
04570 Node->
Extent = NextNode->
Extent;
04571 }
04572
04573
04574
04575
04576
04577
RtlDeleteNoSplay( OverlappedSplayLinks, &LockQueue->SharedLockTree );
04578
FsRtlFreeLockTreeNode( NextNode );
04579 }
04580 }
04581
04582
04583
04584
04585
04586
04587
if (Node->
HoleyNode) {
04588
04589
FsRtlSplitLocks( Node,
NULL,
NULL,
NULL );
04590 }
04591
04592
04593
04594
04595
04596
return TRUE;
04597 }
04598
04599
04600
04601
04602
04603
04604
VOID
04605 FsRtlPrivateInsertExclusiveLock (
04606 IN PLOCK_QUEUE LockQueue,
04607 IN PEX_LOCK NewLock
04608 )
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629 {
04630 PRTL_SPLAY_LINKS OverlappedSplayLinks, ParentSplayLinks;
04631 BOOLEAN
GreaterThan;
04632
04633 OverlappedSplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree,
04634 &NewLock->LockInfo.StartingByte,
04635 &NewLock->LockInfo.EndingByte,
04636 &ParentSplayLinks,
04637 &
GreaterThan );
04638
04639
04640
04641
04642
04643
04644
ASSERT(!OverlappedSplayLinks || NewLock->LockInfo.Length.QuadPart == 0);
04645
04646
04647
04648
04649
04650 RtlInitializeSplayLinks(&NewLock->Links);
04651
04652
if (OverlappedSplayLinks) {
04653
04654
04655
04656
04657
04658
04659
04660
if (RtlRightChild(OverlappedSplayLinks)) {
04661
04662
04663
04664
04665
04666
if (RtlLeftChild(OverlappedSplayLinks)) {
04667
04668
ASSERT(RtlLeftChild(
RtlRealSuccessor(OverlappedSplayLinks)) ==
NULL);
04669 RtlInsertAsLeftChild(
RtlRealSuccessor(OverlappedSplayLinks), &NewLock->Links);
04670
04671 }
else {
04672
04673 RtlInsertAsLeftChild(OverlappedSplayLinks, &NewLock->Links);
04674 }
04675
04676
04677 }
else {
04678
04679 RtlInsertAsRightChild(OverlappedSplayLinks, &NewLock->Links);
04680 }
04681
04682 }
else if (ParentSplayLinks) {
04683
04684
04685
04686
04687
04688
04689
if (
GreaterThan) {
04690
04691
ASSERT(RtlLeftChild(ParentSplayLinks) ==
NULL);
04692 RtlInsertAsLeftChild(ParentSplayLinks, &NewLock->Links);
04693
04694 }
else {
04695
04696
ASSERT(RtlRightChild(ParentSplayLinks) ==
NULL);
04697 RtlInsertAsRightChild(ParentSplayLinks, &NewLock->Links);
04698 }
04699
04700 }
else {
04701
04702
04703
04704
04705
04706 LockQueue->ExclusiveLockTree = &NewLock->Links;
04707 }
04708
04709
04710
04711
04712
04713
return;
04714 }
04715
04716
04717
04718
04719
04720
04721
VOID
04722 FsRtlPrivateCheckWaitingLocks (
04723 IN PLOCK_INFO LockInfo,
04724 IN PLOCK_QUEUE LockQueue,
04725 IN KIRQL OldIrql
04726 )
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749 {
04750 PSINGLE_LIST_ENTRY *pLink, Link;
04751
NTSTATUS NewStatus;
04752 BOOLEAN Result;
04753
04754 pLink = &LockQueue->WaitingLocks.Next;
04755
while ((Link = *pLink) !=
NULL) {
04756
04757
PWAITING_LOCK WaitingLock;
04758
04759
PIRP Irp;
04760
PIO_STACK_LOCATION IrpSp;
04761
04762 BOOLEAN AccessGranted;
04763
04764
FILE_LOCK_INFO FileLockInfo;
04765
04766
04767
04768
04769
04770 WaitingLock = CONTAINING_RECORD( Link,
WAITING_LOCK, Link );
04771
04772
DebugTrace(0,
Dbg,
"FsRtlCheckWaitingLocks, Loop top, WaitingLock = %08lx\n", WaitingLock);
04773
04774
04775
04776
04777
04778
Irp = WaitingLock->
Irp;
04779 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
04780
04781 FileLockInfo.
StartingByte = IrpSp->
Parameters.LockControl.ByteOffset;
04782 FileLockInfo.
Length = *IrpSp->
Parameters.LockControl.Length;
04783 (ULONGLONG)FileLockInfo.
EndingByte.QuadPart =
04784 (ULONGLONG)FileLockInfo.
StartingByte.QuadPart + (ULONGLONG)FileLockInfo.
Length.QuadPart - 1;
04785
04786 FileLockInfo.
FileObject = IrpSp->
FileObject;
04787 FileLockInfo.
ProcessId =
IoGetRequestorProcess(
Irp );
04788 FileLockInfo.
Key = IrpSp->
Parameters.LockControl.Key;
04789 FileLockInfo.
ExclusiveLock =
BooleanFlagOn(IrpSp->
Flags,
SL_EXCLUSIVE_LOCK);
04790
04791
04792
04793
04794
04795
04796
04797
04798
04799
if (FileLockInfo.
ExclusiveLock) {
04800
04801
DebugTrace(0,
Dbg,
"FsRtlCheckWaitingLocks do we have write access?\n", 0);
04802
04803 AccessGranted =
FsRtlPrivateCheckForExclusiveLockAccess(
04804 LockQueue,
04805 &FileLockInfo );
04806 }
else {
04807
04808
DebugTrace(0,
Dbg,
"FsRtlCheckWaitingLocks do we have read access?\n", 0);
04809
04810 AccessGranted =
FsRtlPrivateCheckForSharedLockAccess(
04811 LockQueue,
04812 &FileLockInfo );
04813
04814 }
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
if (AccessGranted) {
04827
04828
DebugTrace(0,
Dbg,
"FsRtlCheckWaitingLocks now has access\n", 0);
04829
04830
04831
04832
04833
04834
IoSetCancelRoutine(
Irp,
NULL );
04835
04836 Result =
FsRtlPrivateInsertLock( LockInfo, IrpSp->
FileObject, &FileLockInfo );
04837
04838
04839
04840
04841
04842
04843 *pLink = Link->Next;
04844
if (Link == LockQueue->WaitingLocksTail.Next) {
04845 LockQueue->WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink;
04846 }
04847
04848
04849
04850
04851
04852
FsRtlReleaseLockQueue(LockQueue, OldIrql);
04853
04854
04855
04856
04857
04858
04859
ObReferenceObject( FileLockInfo.
FileObject );
04860
04861
04862
04863
04864
04865
04866
04867
FsRtlCompleteLockIrp( LockInfo,
04868 WaitingLock->
Context,
04869
Irp,
04870 (Result? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES),
04871 &NewStatus,
04872 FileLockInfo.
FileObject );
04873
04874
if (Result && !
NT_SUCCESS(NewStatus)) {
04875
04876
04877
04878
04879
04880
FsRtlPrivateRemoveLock (
04881 LockInfo,
04882 &FileLockInfo,
04883
FALSE );
04884 }
04885
04886
04887
04888
04889
04890
ObDereferenceObject( FileLockInfo.
FileObject );
04891
04892
04893
04894
04895
04896
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
04897
04898
04899
04900
04901
04902 pLink = &LockQueue->WaitingLocks.Next;
04903
04904
04905
04906
04907
04908
04909
FsRtlFreeWaitingLock( WaitingLock );
04910
04911
04912 }
else {
04913
04914
DebugTrace( 0,
Dbg,
"FsRtlCheckWaitingLocks still no access\n", 0);
04915
04916
04917
04918
04919
04920 pLink = &Link->Next;
04921 }
04922
04923 }
04924
04925
04926
04927
04928
04929
return;
04930 }
04931
04932
04933 BOOLEAN
04934 FsRtlPrivateCheckForExclusiveLockAccess (
04935 IN PLOCK_QUEUE LockQueue,
04936 IN
PFILE_LOCK_INFO FileLockInfo
04937 )
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961 {
04962 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks =
NULL;
04963
PLOCKTREE_NODE Node;
04964
PSH_LOCK ShLock;
04965
PEX_LOCK ExLock;
04966
04967
if (LockQueue->SharedLockTree &&
04968 (SplayLinks =
FsRtlFindFirstOverlappingSharedNode( LockQueue->SharedLockTree,
04969 &FileLockInfo->StartingByte,
04970 &FileLockInfo->EndingByte,
04971 &LastSplayLinks,
NULL))) {
04972
04973 Node = CONTAINING_RECORD(SplayLinks,
LOCKTREE_NODE, Links);
04974
04975
04976
04977
04978
04979
if (Node->
HoleyNode) {
04980
04981 ShLock =
FsRtlFindFirstOverlapInNode( Node,
04982 &FileLockInfo->StartingByte,
04983 &FileLockInfo->EndingByte );
04984
04985 }
else {
04986
04987 ShLock = CONTAINING_RECORD(Node->
Locks.Next,
SH_LOCK, Link);
04988 }
04989
04990
04991
04992
04993
04994
if (ShLock &&
04995 (FileLockInfo->Length.QuadPart || ShLock->
LockInfo.
Length.QuadPart)) {
04996
04997
04998
04999
05000
05001
05002
return FALSE;
05003 }
05004 }
05005
05006
if (LastSplayLinks) {
05007
05008 LockQueue->SharedLockTree =
RtlSplay(LastSplayLinks);
05009 LastSplayLinks =
NULL;
05010 }
05011
05012
if (LockQueue->ExclusiveLockTree &&
05013 (SplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree,
05014 &FileLockInfo->StartingByte,
05015 &FileLockInfo->EndingByte,
05016 &LastSplayLinks,
NULL))) {
05017
05018 ExLock = CONTAINING_RECORD(SplayLinks,
EX_LOCK, Links);
05019
05020
if (FileLockInfo->Length.QuadPart || ExLock->
LockInfo.
Length.QuadPart) {
05021
05022
05023
05024
05025
05026
05027
return FALSE;
05028 }
05029 }
05030
05031
if (LastSplayLinks) {
05032
05033 LockQueue->ExclusiveLockTree =
RtlSplay(LastSplayLinks);
05034 }
05035
05036
05037
05038
05039
05040
05041
return TRUE;
05042 }
05043
05044
05045 BOOLEAN
05046 FsRtlPrivateCheckForSharedLockAccess (
05047 IN PLOCK_QUEUE LockQueue,
05048 IN
PFILE_LOCK_INFO FileLockInfo
05049 )
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074 {
05075
PEX_LOCK Lock;
05076 PRTL_SPLAY_LINKS SplayLinks, LastSplayLinks;
05077 BOOLEAN
Status =
TRUE;
05078
05079
05080
05081
05082
05083
if (LockQueue->ExclusiveLockTree ==
NULL) {
05084
05085
return TRUE;
05086 }
05087
05088
05089
05090
05091
05092
05093
for (SplayLinks =
FsRtlFindFirstOverlappingExclusiveNode( LockQueue->ExclusiveLockTree,
05094 &FileLockInfo->StartingByte,
05095 &FileLockInfo->EndingByte,
05096 &LastSplayLinks,
NULL);
05097 SplayLinks;
05098 SplayLinks =
RtlRealSuccessor(SplayLinks)) {
05099
05100
Lock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
05101
05102
if ((ULONGLONG)
Lock->LockInfo.StartingByte.QuadPart > (ULONGLONG)FileLockInfo->EndingByte.QuadPart) {
05103
05104
05105
05106
05107
05108
05109
break;
05110 }
05111
05112
05113
05114
05115
05116
05117
if ((
Lock->LockInfo.FileObject != FileLockInfo->FileObject) ||
05118 (
Lock->LockInfo.ProcessId != FileLockInfo->ProcessId) ||
05119 (
Lock->LockInfo.Key != FileLockInfo->Key)) {
05120
05121
05122
05123
05124
05125
05126
05127
if (FileLockInfo->Length.QuadPart ||
Lock->LockInfo.Length.QuadPart) {
05128
05129
Status =
FALSE;
05130
break;
05131 }
05132 }
05133 }
05134
05135
if (LastSplayLinks) {
05136
05137 LockQueue->ExclusiveLockTree =
RtlSplay(LastSplayLinks);
05138 }
05139
05140
05141
05142
05143
05144
05145
return Status;
05146 }
05147
05148
05149
VOID
05150 FsRtlPrivateResetLowestLockOffset (
05151 PLOCK_INFO LockInfo
05152 )
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171 {
05172
PEX_LOCK ExLock =
NULL;
05173
PSH_LOCK ShLock =
NULL;
05174
PFILE_LOCK_INFO LowestLockInfo =
NULL;
05175 PRTL_SPLAY_LINKS SplayLinks;
05176
PLOCKTREE_NODE Node;
05177
05178
05179
05180
05181
05182
05183
if (LockInfo->
LowestLockOffset != 0xffffffff &&
05184 (LockInfo->
LockQueue.
SharedLockTree !=
NULL ||
05185 LockInfo->
LockQueue.
ExclusiveLockTree !=
NULL)) {
05186
05187
05188
05189
05190
05191
if (LockInfo->
LockQueue.
SharedLockTree) {
05192
05193 SplayLinks = LockInfo->
LockQueue.
SharedLockTree;
05194
05195
while (RtlLeftChild(SplayLinks) !=
NULL) {
05196
05197 SplayLinks = RtlLeftChild(SplayLinks);
05198 }
05199
05200 Node = CONTAINING_RECORD( SplayLinks,
LOCKTREE_NODE, Links );
05201 ShLock = CONTAINING_RECORD( Node->
Locks.Next,
SH_LOCK, Link );
05202 }
05203
05204
if (LockInfo->
LockQueue.
ExclusiveLockTree) {
05205
05206 SplayLinks = LockInfo->
LockQueue.
ExclusiveLockTree;
05207
05208
while (RtlLeftChild(SplayLinks) !=
NULL) {
05209
05210 SplayLinks = RtlLeftChild(SplayLinks);
05211 }
05212
05213 ExLock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
05214 }
05215
05216
05217
05218
05219
05220
05221
05222
if (ExLock &&
05223 (!ShLock ||
05224 (ULONGLONG)ExLock->
LockInfo.
StartingByte.QuadPart < (ULONGLONG)ShLock->
LockInfo.
StartingByte.QuadPart)) {
05225
05226 LowestLockInfo = &ExLock->
LockInfo;
05227
05228 }
else {
05229
05230 LowestLockInfo = &ShLock->
LockInfo;
05231 }
05232
05233
if (LowestLockInfo->
StartingByte.HighPart == 0) {
05234
05235 LockInfo->
LowestLockOffset = LowestLockInfo->
StartingByte.LowPart;
05236
05237 }
else {
05238
05239 LockInfo->
LowestLockOffset = 0xffffffff;
05240 }
05241
05242 }
else {
05243
05244
05245
05246
05247
05248 LockInfo->
LowestLockOffset = 0xffffffff;
05249 }
05250 }
05251
05252
05253
NTSTATUS
05254 FsRtlPrivateFastUnlockAll (
05255 IN
PFILE_LOCK FileLock,
05256 IN
PFILE_OBJECT FileObject,
05257 IN
PEPROCESS ProcessId,
05258 IN ULONG Key,
05259 IN BOOLEAN MatchKey,
05260 IN PVOID Context OPTIONAL
05261 )
05262
05263
05264
05265
05266
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295 {
05296
PLOCK_INFO LockInfo;
05297
PLOCK_QUEUE LockQueue;
05298 PSINGLE_LIST_ENTRY *pLink, *SavepLink, Link;
05299
NTSTATUS NewStatus;
05300 KIRQL OldIrql;
05301 LARGE_INTEGER MaxOffset, SaveEndingByte;
05302 BOOLEAN UnlockRoutine;
05303
PSH_LOCK ShLock;
05304
PEX_LOCK ExLock;
05305 PRTL_SPLAY_LINKS SplayLinks, SuccessorLinks;
05306
PLOCKTREE_NODE Node;
05307
05308
05309
DebugTrace(+1,
Dbg,
"FsRtlPrivateFastUnlockAll, FileLock = %08lx\n", FileLock);
05310
05311
if ((LockInfo = FileLock->LockInformation) ==
NULL) {
05312
05313
05314
05315
05316
05317
DebugTrace(+1,
Dbg,
"FsRtlPrivateFastUnlockAll, No LockInfo\n", FileLock);
05318
return STATUS_RANGE_NOT_LOCKED;
05319 }
05320
05321 FileObject->LastLock =
NULL;
05322
05323 LockQueue = &LockInfo->
LockQueue;
05324
05325
05326
05327
05328
05329
05330
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
05331
05332
if (LockQueue->
SharedLockTree ==
NULL && LockQueue->
ExclusiveLockTree ==
NULL) {
05333
05334
05335
05336
05337
05338
DebugTrace(+1,
Dbg,
"FsRtlPrivateFastUnlockAll, No LockTrees\n", FileLock);
05339
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05340
05341
return STATUS_RANGE_NOT_LOCKED;
05342 }
05343
05344
05345
05346
05347
05348
if (LockQueue->
SharedLockTree !=
NULL) {
05349
05350
05351
05352
05353
05354 SplayLinks = LockQueue->
SharedLockTree;
05355
05356
while (RtlLeftChild(SplayLinks) !=
NULL) {
05357
05358 SplayLinks = RtlLeftChild(SplayLinks);
05359 }
05360
05361
05362
05363
05364
05365 UnlockRoutine =
FALSE;
05366
05367
for (;
05368 SplayLinks;
05369 SplayLinks = SuccessorLinks) {
05370
05371 Node = CONTAINING_RECORD(SplayLinks,
LOCKTREE_NODE, Links );
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382 SuccessorLinks =
RtlRealSuccessor(SplayLinks);
05383
05384
05385
05386
05387
05388
05389 SavepLink =
NULL;
05390 SaveEndingByte.QuadPart = 0;
05391
05392 pLink = &Node->
Locks.Next;
05393
while ((Link = *pLink) !=
NULL) {
05394
05395 ShLock = CONTAINING_RECORD( Link,
SH_LOCK, Link );
05396
05397
DebugTrace(0,
Dbg,
"Top of ShLock Loop, Lock = %08lx\n", ShLock );
05398
05399
if ((ShLock->
LockInfo.
FileObject == FileObject) &&
05400 (ShLock->
LockInfo.
ProcessId == ProcessId) &&
05401 (!MatchKey || ShLock->
LockInfo.
Key ==
Key)) {
05402
05403
DebugTrace(0,
Dbg,
"Found one to unlock\n", 0);
05404
05405
05406
05407
05408
05409
05410
05411
05412
if (SavepLink ==
NULL) {
05413
05414
05415
05416
05417
05418 SavepLink = pLink;
05419 }
05420
05421
if ((ULONGLONG)ShLock->
LockInfo.
EndingByte.QuadPart > (ULONGLONG)SaveEndingByte.QuadPart) {
05422
05423
05424
05425
05426
05427 SaveEndingByte.QuadPart = ShLock->
LockInfo.
EndingByte.QuadPart;
05428 }
05429
05430
if (*pLink == Node->
Tail.Next) {
05431
05432
05433
05434
05435
05436
05437
05438 Node->
Tail.Next = CONTAINING_RECORD( pLink, SINGLE_LIST_ENTRY, Next );
05439 }
05440
05441 *pLink = Link->Next;
05442
05443
if (LockInfo->
UnlockRoutine !=
NULL) {
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453 UnlockRoutine =
TRUE;
05454
05455
break;
05456 }
05457
05458
FsRtlFreeSharedLock( ShLock );
05459
05460 }
else {
05461
05462
05463
05464
05465
05466 pLink = &Link->Next;
05467 }
05468
05469
if (SavepLink ==
NULL && (ULONGLONG)ShLock->
LockInfo.
EndingByte.QuadPart > (ULONGLONG)MaxOffset.QuadPart) {
05470
05471
05472
05473
05474
05475 MaxOffset.QuadPart = ShLock->
LockInfo.
EndingByte.QuadPart;
05476 }
05477 }
05478
05479
if (SavepLink) {
05480
05481
05482
05483
05484
05485
if (Node->
Locks.Next ==
NULL) {
05486
05487
05488
05489
05490
05491 LockQueue->
SharedLockTree =
RtlDelete(SplayLinks);
05492
05493
FsRtlFreeLockTreeNode(Node);
05494
05495 }
else {
05496
05497
05498
05499
05500
05501
05502
05503
05504
FsRtlSplitLocks(Node, SavepLink, &SaveEndingByte, &MaxOffset);
05505 }
05506 }
05507
05508
if (UnlockRoutine) {
05509
05510
05511
05512
05513
05514
05515
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05516
05517 LockInfo->
UnlockRoutine(Context, &ShLock->
LockInfo);
05518
05519
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
05520
05521
FsRtlFreeSharedLock(ShLock);
05522
05523 UnlockRoutine =
FALSE;
05524
05525
05526
05527
05528
05529
05530
if (SuccessorLinks = LockQueue->
SharedLockTree) {
05531
05532
while (RtlLeftChild(SuccessorLinks) !=
NULL) {
05533
05534 SuccessorLinks = RtlLeftChild(SuccessorLinks);
05535 }
05536 }
05537 }
05538 }
05539 }
05540
05541
05542
05543
05544
05545
if (LockQueue->
ExclusiveLockTree !=
NULL) {
05546
05547 SplayLinks = LockQueue->
ExclusiveLockTree;
05548
05549
while (RtlLeftChild(SplayLinks) !=
NULL) {
05550
05551 SplayLinks = RtlLeftChild(SplayLinks);
05552 }
05553
05554
05555
05556
05557
05558 UnlockRoutine =
FALSE;
05559
05560
for (; SplayLinks;
05561 SplayLinks = SuccessorLinks ) {
05562
05563 SuccessorLinks =
RtlRealSuccessor(SplayLinks);
05564
05565 ExLock = CONTAINING_RECORD( SplayLinks,
EX_LOCK, Links );
05566
05567
DebugTrace(0,
Dbg,
"Top of ExLock Loop, Lock = %08lx\n", ExLock );
05568
05569
if ((ExLock->
LockInfo.
FileObject == FileObject) &&
05570 (ExLock->
LockInfo.
ProcessId == ProcessId) &&
05571 (!MatchKey || ExLock->
LockInfo.
Key ==
Key)) {
05572
05573 LockQueue->
ExclusiveLockTree =
RtlDelete(&ExLock->
Links);
05574
05575
if (LockInfo->
UnlockRoutine !=
NULL) {
05576
05577
05578
05579
05580
05581
05582
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05583
05584 LockInfo->
UnlockRoutine(Context, &ExLock->
LockInfo);
05585
05586
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
05587
05588
05589
05590
05591
05592
05593
if (SuccessorLinks = LockQueue->
ExclusiveLockTree) {
05594
05595
while (RtlLeftChild(SuccessorLinks) !=
NULL) {
05596
05597 SuccessorLinks = RtlLeftChild(SuccessorLinks);
05598 }
05599 }
05600 }
05601
05602
FsRtlFreeExclusiveLock(ExLock);
05603 }
05604 }
05605 }
05606
05607
05608
05609
05610
05611
05612 pLink = &LockQueue->
WaitingLocks.Next;
05613
while ((Link = *pLink) !=
NULL) {
05614
05615
PWAITING_LOCK WaitingLock;
05616
PIRP WaitingIrp;
05617
PIO_STACK_LOCATION WaitingIrpSp;
05618
05619 WaitingLock = CONTAINING_RECORD( Link,
WAITING_LOCK, Link );
05620
05621
DebugTrace(0,
Dbg,
"Top of Waiting Loop, WaitingLock = %08lx\n", WaitingLock);
05622
05623
05624
05625
05626
05627 WaitingIrp = WaitingLock->
Irp;
05628 WaitingIrpSp =
IoGetCurrentIrpStackLocation( WaitingIrp );
05629
05630
if ((FileObject == WaitingIrpSp->
FileObject) &&
05631 (ProcessId ==
IoGetRequestorProcess( WaitingIrp )) &&
05632 (!MatchKey ||
Key == WaitingIrpSp->
Parameters.LockControl.Key)) {
05633
05634
DebugTrace(0,
Dbg,
"Found a waiting lock to abort\n", 0);
05635
05636
05637
05638
05639
05640
IoSetCancelRoutine( WaitingIrp,
NULL );
05641 WaitingIrp->
IoStatus.Information = 0;
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651 *pLink = Link->Next;
05652
if (Link == LockQueue->
WaitingLocksTail.Next) {
05653 LockQueue->
WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink;
05654 }
05655
05656
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05657
05658
05659
05660
05661
05662
FsRtlCompleteLockIrp( LockInfo,
05663 WaitingLock->
Context,
05664 WaitingIrp,
05665 STATUS_SUCCESS,
05666 &NewStatus,
05667
NULL );
05668
05669
05670
05671
05672
05673
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
05674
05675
05676
05677
05678
05679 pLink = &LockQueue->
WaitingLocks.Next;
05680
05681
05682
05683
05684
05685
FsRtlFreeWaitingLock( WaitingLock );
05686
continue;
05687 }
05688
05689
05690
05691
05692
05693 pLink = &Link->Next;
05694 }
05695
05696
05697
05698
05699
05700
05701
FsRtlPrivateCheckWaitingLocks( LockInfo, LockQueue, OldIrql );
05702
05703
05704
05705
05706
05707
FsRtlPrivateResetLowestLockOffset( LockInfo );
05708
05709
FsRtlReleaseLockQueue( LockQueue, OldIrql );
05710
05711
05712
05713
05714
05715
DebugTrace(-1,
Dbg,
"FsRtlFastUnlockAll -> VOID\n", 0);
05716
return STATUS_SUCCESS;
05717 }
05718
05719
05720
VOID
05721 FsRtlPrivateCancelFileLockIrp (
05722 IN
PDEVICE_OBJECT DeviceObject,
05723 IN
PIRP Irp
05724 )
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747 {
05748 PSINGLE_LIST_ENTRY *pLink, Link;
05749
PLOCK_INFO LockInfo;
05750
PLOCK_QUEUE LockQueue;
05751 KIRQL OldIrql;
05752
NTSTATUS NewStatus;
05753
05754
05755 UNREFERENCED_PARAMETER( DeviceObject );
05756
05757
05758
05759
05760
05761
05762 LockInfo = (
PLOCK_INFO) (
Irp->
IoStatus.Information);
05763
05764
05765
05766
05767
05768 LockQueue = &LockInfo->
LockQueue;
05769
05770
05771
05772
05773
05774
05775
05776
05777
05778
if (DeviceObject) {
05779
05780
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
05781
FsRtlReacquireLockQueue(LockInfo, LockQueue, &OldIrql);
05782
05783 }
else {
05784
05785 OldIrql =
Irp->
CancelIrql;
05786 }
05787
05788
05789
05790
05791 pLink = &LockQueue->
WaitingLocks.Next;
05792
while ((Link = *pLink) !=
NULL) {
05793
05794
PWAITING_LOCK WaitingLock;
05795
05796
05797
05798
05799
05800 WaitingLock = CONTAINING_RECORD( Link,
WAITING_LOCK, Link );
05801
05802
DebugTrace(0,
Dbg,
"FsRtlPrivateCancelFileLockIrp, Loop top, WaitingLock = %08lx\n", WaitingLock);
05803
05804
if( WaitingLock->
Irp !=
Irp ) {
05805
05806 pLink = &Link->Next;
05807
continue;
05808 }
05809
05810
05811
05812
05813
05814 *pLink = Link->Next;
05815
if (Link == LockQueue->
WaitingLocksTail.Next) {
05816
05817 LockQueue->
WaitingLocksTail.Next = (PSINGLE_LIST_ENTRY) pLink;
05818 }
05819
05820
Irp->
IoStatus.Information = 0;
05821
05822
05823
05824
05825
05826
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05827
05828
05829
05830
05831
05832
FsRtlCompleteLockIrp( LockInfo,
05833 WaitingLock->
Context,
05834
Irp,
05835 STATUS_CANCELLED,
05836 &NewStatus,
05837
NULL );
05838
05839
05840
05841
05842
05843
FsRtlFreeWaitingLock( WaitingLock );
05844
05845
05846
05847
05848
05849
return;
05850 }
05851
05852
05853
05854
05855
05856
FsRtlReleaseLockQueue(LockQueue, OldIrql);
05857
05858
return;
05859 }
05860