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
#include "FsRtlP.h"
00045
00046
00047
00048
00049
00050 #define Dbg (0x08000000)
00051
00052
00053
00054
00055
00056
00057 #define FILTER_OPLOCK_VALID_FLAGS ( \
00058
FILE_READ_ATTRIBUTES | \
00059
FILE_WRITE_ATTRIBUTES | \
00060
FILE_READ_DATA | \
00061
FILE_READ_EA | \
00062
FILE_EXECUTE | \
00063
SYNCHRONIZE | \
00064
READ_CONTROL \
00065
)
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define NO_OPLOCK (0x00000001)
00077 #define LEVEL_I_OPLOCK (0x00000002)
00078 #define BATCH_OPLOCK (0x00000004)
00079 #define FILTER_OPLOCK (0x00000008)
00080 #define LEVEL_II_OPLOCK (0x00000010)
00081
00082 #define OPLOCK_TYPE_MASK (0x0000001f)
00083
00084 #define EXCLUSIVE (0x00000040)
00085 #define PENDING (0x00000080)
00086
00087 #define OPLOCK_HELD_MASK (0x000000c0)
00088
00089 #define BREAK_TO_II (0x00000100)
00090 #define BREAK_TO_NONE (0x00000200)
00091 #define BREAK_TO_II_TO_NONE (0x00000400)
00092 #define CLOSE_PENDING (0x00000800)
00093
00094 #define OPLOCK_BREAK_MASK (0x00000f00)
00095
00096
00097
00098
00099
00100 #define NoOplocksHeld (NO_OPLOCK)
00101
00102 #define OplockIGranted (LEVEL_I_OPLOCK | EXCLUSIVE)
00103 #define OpBatchGranted (BATCH_OPLOCK | EXCLUSIVE)
00104 #define OpFilterGranted (FILTER_OPLOCK | EXCLUSIVE)
00105 #define OpFilterReqPending (FILTER_OPLOCK | EXCLUSIVE | PENDING )
00106
00107 #define OplockBreakItoII (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II)
00108 #define OpBatchBreaktoII (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II)
00109 #define OpFilterBreaktoII (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II)
00110
00111 #define OplockBreakItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
00112 #define OpBatchBreaktoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
00113 #define OpFilterBreaktoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_NONE)
00114
00115 #define OplockBreakItoIItoNone (LEVEL_I_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
00116 #define OpBatchBreaktoIItoNone (BATCH_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
00117 #define OpFilterBreaktoIItoNone (FILTER_OPLOCK | EXCLUSIVE | BREAK_TO_II_NONE)
00118
00119 #define OpBatchClosePending (BATCH_OPLOCK | EXCLUSIVE | CLOSE_PENDING)
00120 #define OpFilterClosePending (FILTER_OPLOCK | EXCLUSIVE | CLOSE_PENDING)
00121
00122 #define OplockIIGranted (LEVEL_II_OPLOCK)
00123
00124
00125
00126
00127
00128 typedef ULONG
OPLOCK_STATE;
00129
00130
00131
00132
00133
00134
00135 typedef struct _NONOPAQUE_OPLOCK {
00136
00137
00138
00139
00140
00141
00142
00143
PIRP IrpExclusiveOplock;
00144
00145
00146
00147
00148
00149
00150
PFILE_OBJECT FileObject;
00151
00152
00153
00154
00155
00156
00157 LIST_ENTRY
IrpOplocksII;
00158
00159
00160
00161
00162
00163
00164 LIST_ENTRY
WaitingIrps;
00165
00166
00167
00168
00169
00170
OPLOCK_STATE OplockState;
00171
00172
00173
00174
00175
00176
PFAST_MUTEX FastMutex;
00177
00178 }
NONOPAQUE_OPLOCK, *
PNONOPAQUE_OPLOCK;
00179
00180
00181
00182
00183
00184
00185
00186 typedef struct _WAITING_IRP {
00187
00188
00189
00190
00191
00192 LIST_ENTRY
Links;
00193
00194
00195
00196
00197
00198
PIRP Irp;
00199
00200
00201
00202
00203
00204
00205
POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine;
00206
00207
00208
00209
00210
00211 PVOID
Context;
00212
00213
00214
00215
00216
00217
00218
PKEVENT Event;
00219
00220
00221
00222
00223
00224
00225
00226 ULONG
Information;
00227
00228 }
WAITING_IRP, *
PWAITING_IRP;
00229
00230
00231
00232
00233
00234
#undef MODULE_POOL_TAG
00235 #define MODULE_POOL_TAG ('orSF')
00236
00237
00238
00239
00240
00241
00242
PNONOPAQUE_OPLOCK
00243
FsRtlAllocateOplock (
00244 );
00245
00246
NTSTATUS
00247
FsRtlRequestExclusiveOplock (
00248 IN OUT PNONOPAQUE_OPLOCK *Oplock,
00249 IN
PIO_STACK_LOCATION IrpSp,
00250 IN
PIRP Irp OPTIONAL,
00251 IN OPLOCK_STATE NextOplockState
00252 );
00253
00254
NTSTATUS
00255
FsRtlRequestOplockII (
00256 IN OUT PNONOPAQUE_OPLOCK *Oplock,
00257 IN
PIO_STACK_LOCATION IrpSp,
00258 IN
PIRP Irp
00259 );
00260
00261
NTSTATUS
00262
FsRtlAcknowledgeOplockBreak (
00263 IN OUT PNONOPAQUE_OPLOCK Oplock,
00264 IN
PIO_STACK_LOCATION IrpSp,
00265 IN
PIRP Irp,
00266 IN BOOLEAN GrantLevelII
00267 );
00268
00269
NTSTATUS
00270
FsRtlOpBatchBreakClosePending (
00271 IN OUT PNONOPAQUE_OPLOCK Oplock,
00272 IN
PIO_STACK_LOCATION IrpSp,
00273 IN
PIRP Irp
00274 );
00275
00276
NTSTATUS
00277
FsRtlOplockBreakNotify (
00278 IN OUT PNONOPAQUE_OPLOCK Oplock,
00279 IN
PIO_STACK_LOCATION IrpSp,
00280 IN
PIRP Irp
00281 );
00282
00283
VOID
00284
FsRtlOplockCleanup (
00285 IN OUT PNONOPAQUE_OPLOCK Oplock,
00286 IN
PIO_STACK_LOCATION IrpSp
00287 );
00288
00289
NTSTATUS
00290
FsRtlOplockBreakToII (
00291 IN OUT PNONOPAQUE_OPLOCK Oplock,
00292 IN
PIO_STACK_LOCATION IrpSp,
00293 IN
PIRP Irp,
00294 IN PVOID Context,
00295 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
00296 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL
00297 );
00298
00299
NTSTATUS
00300
FsRtlOplockBreakToNone (
00301 IN OUT PNONOPAQUE_OPLOCK Oplock,
00302 IN
PIO_STACK_LOCATION IrpSp,
00303 IN
PIRP Irp,
00304 IN PVOID Context,
00305 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
00306 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL
00307 );
00308
00309
VOID
00310
FsRtlRemoveAndCompleteIrp (
00311 IN PLIST_ENTRY Link
00312 );
00313
00314
NTSTATUS
00315
FsRtlWaitOnIrp (
00316 IN OUT PNONOPAQUE_OPLOCK Oplock,
00317 IN
PIRP Irp,
00318 IN PVOID Context,
00319 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
00320 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL,
00321 IN
PKEVENT Event
00322 );
00323
00324
VOID
00325
FsRtlCompletionRoutinePriv (
00326 IN PVOID Context,
00327 IN
PIRP Irp
00328 );
00329
00330
VOID
00331
FsRtlCancelWaitIrp (
00332 IN
PDEVICE_OBJECT DeviceObject,
00333 IN
PIRP Irp
00334 );
00335
00336
VOID
00337
FsRtlCancelOplockIIIrp (
00338 IN
PDEVICE_OBJECT DeviceObject,
00339 IN
PIRP Irp
00340 );
00341
00342
VOID
00343
FsRtlCancelExclusiveIrp (
00344 IN
PDEVICE_OBJECT DeviceObject,
00345 IN
PIRP Irp
00346 );
00347
00348
VOID
00349
FsRtlRemoveAndCompleteWaitIrp (
00350 IN PWAITING_IRP WaitingIrp
00351 );
00352
00353
VOID
00354
FsRtlNotifyCompletion (
00355 IN PVOID Context,
00356 IN
PIRP Irp
00357 );
00358
00359
#ifdef ALLOC_PRAGMA
00360
#pragma alloc_text(PAGE, FsRtlAllocateOplock)
00361
#pragma alloc_text(PAGE, FsRtlCompletionRoutinePriv)
00362
#pragma alloc_text(PAGE, FsRtlCurrentBatchOplock)
00363
#pragma alloc_text(PAGE, FsRtlInitializeOplock)
00364
#pragma alloc_text(PAGE, FsRtlNotifyCompletion)
00365
#pragma alloc_text(PAGE, FsRtlOpBatchBreakClosePending)
00366
#pragma alloc_text(PAGE, FsRtlOplockBreakNotify)
00367
#pragma alloc_text(PAGE, FsRtlOplockFsctrl)
00368
#pragma alloc_text(PAGE, FsRtlOplockIsFastIoPossible)
00369
#endif
00370
00371
00372
VOID
00373 FsRtlInitializeOplock (
00374 IN OUT POPLOCK Oplock
00375 )
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 {
00397 UNREFERENCED_PARAMETER( Oplock );
00398
00399
PAGED_CODE();
00400
00401
DebugTrace(+1,
Dbg,
"FsRtlInitializeOplock: Oplock -> %08lx\n", *Oplock );
00402
00403
00404
00405
00406
00407
DebugTrace(-1,
Dbg,
"FsRtlInitializeOplock: Exit\n", 0);
00408
return;
00409 }
00410
00411
00412
VOID
00413 FsRtlUninitializeOplock (
00414 IN OUT POPLOCK Oplock
00415 )
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 {
00437
PNONOPAQUE_OPLOCK ThisOplock;
00438
00439
DebugTrace(+1,
Dbg,
"FsRtlUninitializeOplock: Oplock -> %08lx\n", *Oplock );
00440
00441
00442
00443
00444
00445
00446
if (*Oplock !=
NULL) {
00447
00448
00449
00450
00451
00452 ThisOplock = (
PNONOPAQUE_OPLOCK) *Oplock;
00453
00454 *Oplock =
NULL;
00455
00456
00457
00458
00459
00460
00461
ExAcquireFastMutexUnsafe( ThisOplock->
FastMutex );
00462
00463
try {
00464
00465
PIRP Irp;
00466
00467
00468
00469
00470
00471
while (!IsListEmpty( &ThisOplock->
WaitingIrps )) {
00472
00473
PWAITING_IRP WaitingIrp;
00474
PIRP ThisIrp;
00475
00476 WaitingIrp = CONTAINING_RECORD( ThisOplock->
WaitingIrps.Flink,
00477
WAITING_IRP,
00478 Links );
00479
00480 RemoveHeadList( &ThisOplock->
WaitingIrps );
00481
00482 ThisIrp = WaitingIrp->
Irp;
00483
00484
IoAcquireCancelSpinLock( &ThisIrp->
CancelIrql );
00485
00486
IoSetCancelRoutine( ThisIrp,
NULL );
00487
IoReleaseCancelSpinLock( ThisIrp->
CancelIrql );
00488
00489 ThisIrp->
IoStatus.Information = 0;
00490
00491
00492
00493
00494
00495 WaitingIrp->
CompletionRoutine( WaitingIrp->
Context,
00496 WaitingIrp->
Irp );
00497
00498
ExFreePool( WaitingIrp );
00499 }
00500
00501
00502
00503
00504
00505
while (!IsListEmpty( &ThisOplock->
IrpOplocksII )) {
00506
00507
Irp = CONTAINING_RECORD( ThisOplock->
IrpOplocksII.Flink,
00508
IRP,
00509 Tail.Overlay.ListEntry );
00510
00511 RemoveHeadList( &ThisOplock->
IrpOplocksII );
00512
00513
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
00514
00515
IoSetCancelRoutine(
Irp,
NULL );
00516
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
00517
00518
00519
00520
00521
00522
ObDereferenceObject(
IoGetCurrentIrpStackLocation(
Irp )->FileObject );
00523
00524
Irp->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
00525
FsRtlCompleteRequest(
Irp, STATUS_SUCCESS );
00526 }
00527
00528
00529
00530
00531
00532
if (ThisOplock->
IrpExclusiveOplock !=
NULL) {
00533
00534
Irp = ThisOplock->
IrpExclusiveOplock;
00535
00536
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
00537
00538
IoSetCancelRoutine(
Irp,
NULL );
00539
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
00540
00541
Irp->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
00542
FsRtlCompleteRequest(
Irp, STATUS_SUCCESS );
00543
00544 ThisOplock->
IrpExclusiveOplock =
NULL;
00545
00546
if (ThisOplock->
FileObject !=
NULL) {
00547
00548
ObDereferenceObject( ThisOplock->
FileObject );
00549 }
00550 }
00551
00552 } finally {
00553
00554
00555
00556
00557
00558
00559
ExReleaseFastMutexUnsafe( ThisOplock->
FastMutex );
00560 }
00561
00562
00563
00564
00565
00566
ExFreePool( ThisOplock->
FastMutex );
00567
00568
00569
00570
00571
00572
ExFreePool( ThisOplock );
00573 }
00574
00575
DebugTrace( -1,
Dbg,
"FsRtlUninitializeOplock: Exit\n", 0 );
00576
return;
00577 }
00578
00579
00580
NTSTATUS
00581 FsRtlOplockFsctrl (
00582 IN POPLOCK Oplock,
00583 IN
PIRP Irp,
00584 IN ULONG OpenCount
00585 )
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 {
00624
NTSTATUS Status;
00625
PIO_STACK_LOCATION IrpSp;
00626
OPLOCK_STATE OplockState;
00627
00628
PAGED_CODE();
00629
00630
00631
00632
00633
00634 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
00635
00636
DebugTrace(+1,
Dbg,
"FsRtlOplockFsctrl: Entered\n", 0);
00637
DebugTrace( 0,
Dbg,
"FsRtlOplockFsctrl: Oplock -> %08lx\n", *Oplock );
00638
DebugTrace( 0,
Dbg,
"FsRtlOplockFsctrl: Irp -> %08lx\n",
Irp );
00639
00640
00641
00642
00643
00644
00645
if (IrpSp->
MajorFunction ==
IRP_MJ_CREATE) {
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
if ((OpenCount != 1) ||
00660 (
FlagOn( IrpSp->
Parameters.Create.SecurityContext->DesiredAccess,
00661 ~(FILE_READ_ATTRIBUTES))) ||
00662 ((IrpSp->
Parameters.Create.ShareAccess &
00663 (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)) !=
00664 (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE))) {
00665
00666
Status = STATUS_OPLOCK_NOT_GRANTED;
00667
00668 }
else {
00669
00670
Status =
FsRtlRequestExclusiveOplock( (
PNONOPAQUE_OPLOCK *) Oplock,
00671 IrpSp,
00672
NULL,
00673
OpFilterReqPending );
00674 }
00675
00676
00677
00678
00679
00680 }
else {
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 OplockState =
LEVEL_I_OPLOCK;
00691
00692
switch (IrpSp->
Parameters.FileSystemControl.FsControlCode) {
00693
00694
case FSCTL_REQUEST_FILTER_OPLOCK :
00695
00696 OplockState *= 2;
00697
00698
case FSCTL_REQUEST_BATCH_OPLOCK :
00699
00700 OplockState *= 2;
00701
00702
case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
00703
00704
00705
00706
00707
00708
SetFlag( OplockState,
EXCLUSIVE );
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
if ((OpenCount != 1) ||
00723
IoIsOperationSynchronous(
Irp ) ||
00724
FlagOn(
Irp->
Flags,
IRP_INPUT_OPERATION ) ||
00725
FlagOn( IrpSp->
FileObject->
Flags,
FO_CLEANUP_COMPLETE )) {
00726
00727
FsRtlCompleteRequest(
Irp, STATUS_OPLOCK_NOT_GRANTED );
00728
Status = STATUS_OPLOCK_NOT_GRANTED;
00729
00730 }
else {
00731
00732
Status =
FsRtlRequestExclusiveOplock( (
PNONOPAQUE_OPLOCK *) Oplock,
00733 IrpSp,
00734
Irp,
00735 OplockState );
00736 }
00737
00738
break;
00739
00740
case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
if ((OpenCount != 0) ||
00759
IoIsOperationSynchronous(
Irp ) ||
00760
FlagOn(
Irp->
Flags,
IRP_INPUT_OPERATION ) ||
00761
FlagOn( IrpSp->
FileObject->
Flags,
FO_CLEANUP_COMPLETE )) {
00762
00763
FsRtlCompleteRequest(
Irp, STATUS_OPLOCK_NOT_GRANTED );
00764
Status = STATUS_OPLOCK_NOT_GRANTED;
00765
00766 }
else {
00767
00768
Status =
FsRtlRequestOplockII( (
PNONOPAQUE_OPLOCK *) Oplock,
00769 IrpSp,
00770
Irp );
00771 }
00772
00773
break;
00774
00775
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
00776
00777
Status =
FsRtlAcknowledgeOplockBreak( (
PNONOPAQUE_OPLOCK) *Oplock,
00778 IrpSp,
00779
Irp,
00780
TRUE );
00781
break;
00782
00783
case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
00784
00785
Status =
FsRtlAcknowledgeOplockBreak( (
PNONOPAQUE_OPLOCK) *Oplock,
00786 IrpSp,
00787
Irp,
00788
FALSE );
00789
break;
00790
00791
case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
00792
00793
Status =
FsRtlOpBatchBreakClosePending( (
PNONOPAQUE_OPLOCK) *Oplock,
00794 IrpSp,
00795
Irp );
00796
break;
00797
00798
case FSCTL_OPLOCK_BREAK_NOTIFY :
00799
00800
Status =
FsRtlOplockBreakNotify( (
PNONOPAQUE_OPLOCK) *Oplock,
00801 IrpSp,
00802
Irp );
00803
break;
00804
00805
default :
00806
00807
DebugTrace( 0,
00808
Dbg,
00809
"Invalid Control Code\n",
00810 0);
00811
00812
FsRtlCompleteRequest(
Irp, STATUS_INVALID_PARAMETER );
00813
Status = STATUS_INVALID_PARAMETER;
00814 }
00815 }
00816
00817
DebugTrace(-1,
Dbg,
"FsRtlOplockFsctrl: Exit -> %08lx\n",
Status );
00818
return Status;
00819 }
00820
00821
00822
NTSTATUS
00823 FsRtlCheckOplock (
00824 IN POPLOCK Oplock,
00825 IN
PIRP Irp,
00826 IN PVOID Context,
00827 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
00828 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL
00829 )
00830
00831
00832
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
00866
00867
00868
00869 {
00870
NTSTATUS Status = STATUS_SUCCESS;
00871
PNONOPAQUE_OPLOCK ThisOplock = *Oplock;
00872
00873
PIO_STACK_LOCATION IrpSp;
00874
00875
DebugTrace( +1,
Dbg,
"FsRtlCheckOplock: Entered\n", 0 );
00876
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
00877
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
00878
00879
00880
00881
00882
00883
00884
if ((ThisOplock !=
NULL) &&
00885 !
FlagOn(
Irp->
Flags,
IRP_PAGING_IO )) {
00886
00887
OPLOCK_STATE OplockState;
00888
PFILE_OBJECT OplockFileObject;
00889
00890 BOOLEAN BreakToII;
00891 BOOLEAN BreakToNone;
00892
00893 ULONG CreateDisposition;
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 OplockFileObject = ThisOplock->
FileObject;
00904 OplockState = ThisOplock->
OplockState;
00905
00906
00907
00908
00909
00910
00911
if (OplockState !=
NoOplocksHeld) {
00912
00913 BreakToII =
FALSE;
00914 BreakToNone =
FALSE;
00915
00916 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
00917
00918
00919
00920
00921
00922
switch (IrpSp->
MajorFunction) {
00923
00924
case IRP_MJ_CREATE :
00925
00926
00927
00928
00929
00930
00931
00932
if (!
FlagOn( IrpSp->
Parameters.Create.SecurityContext->DesiredAccess,
00933 ~(FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE) ) &&
00934 !
FlagOn( IrpSp->
Parameters.Create.Options, FILE_RESERVE_OPFILTER )) {
00935
00936
break;
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
if (
FlagOn( OplockState,
FILTER_OPLOCK ) &&
00946 !
FlagOn( IrpSp->
Parameters.Create.SecurityContext->DesiredAccess,
00947 ~
FILTER_OPLOCK_VALID_FLAGS ) &&
00948
FlagOn( IrpSp->
Parameters.Create.ShareAccess, FILE_SHARE_READ )) {
00949
00950
break;
00951 }
00952
00953
00954
00955
00956
00957 CreateDisposition = (IrpSp->
Parameters.Create.Options >> 24) & 0x000000ff;
00958
00959
if ((CreateDisposition == FILE_SUPERSEDE) ||
00960 (CreateDisposition == FILE_OVERWRITE) ||
00961 (CreateDisposition == FILE_OVERWRITE_IF) ||
00962
FlagOn( IrpSp->
Parameters.Create.Options, FILE_RESERVE_OPFILTER )) {
00963
00964 BreakToNone =
TRUE;
00965
00966 }
else {
00967
00968 BreakToII =
TRUE;
00969 }
00970
00971
break;
00972
00973
case IRP_MJ_READ :
00974
00975
00976
00977
00978
00979
00980
00981
if (!
FlagOn( OplockState,
FILTER_OPLOCK )) {
00982
00983 BreakToII =
TRUE;
00984 }
00985
00986
break;
00987
00988
case IRP_MJ_FLUSH_BUFFERS :
00989
00990 BreakToII =
TRUE;
00991
break;
00992
00993
case IRP_MJ_CLEANUP :
00994
00995
FsRtlOplockCleanup( (
PNONOPAQUE_OPLOCK) *Oplock,
00996 IrpSp );
00997
00998
break;
00999
01000
case IRP_MJ_LOCK_CONTROL :
01001
01002
01003
01004
01005
01006
01007
01008
if (
FlagOn( OplockState,
FILTER_OPLOCK )) {
01009
01010
break;
01011 }
01012
01013
case IRP_MJ_WRITE :
01014
01015 BreakToNone =
TRUE;
01016
break;
01017
01018
case IRP_MJ_SET_INFORMATION :
01019
01020
01021
01022
01023
01024
01025
switch (IrpSp->
Parameters.SetFile.FileInformationClass) {
01026
01027
case FileEndOfFileInformation :
01028
01029
01030
01031
01032
01033
if (IrpSp->
Parameters.SetFile.AdvanceOnly) {
01034
01035
break;
01036 }
01037
01038
case FileAllocationInformation :
01039
01040 BreakToNone =
TRUE;
01041
break;
01042
01043
case FileRenameInformation :
01044
case FileLinkInformation :
01045
01046
if (
FlagOn( OplockState,
BATCH_OPLOCK |
FILTER_OPLOCK )) {
01047
01048 BreakToNone =
TRUE;
01049 }
01050
01051
break;
01052 }
01053
01054
case IRP_MJ_FILE_SYSTEM_CONTROL :
01055
01056
01057
01058
01059
01060
if (IrpSp->
Parameters.FileSystemControl.FsControlCode == FSCTL_SET_ZERO_DATA) {
01061
01062 BreakToNone =
TRUE;
01063 }
01064 }
01065
01066
if (BreakToII) {
01067
01068
01069
01070
01071
01072
01073
01074
01075
if ((OplockState !=
OplockIIGranted) &&
01076 (OplockFileObject != IrpSp->
FileObject)) {
01077
01078
Status =
FsRtlOplockBreakToII( (
PNONOPAQUE_OPLOCK) *Oplock,
01079 IrpSp,
01080
Irp,
01081 Context,
01082 CompletionRoutine,
01083 PostIrpRoutine );
01084 }
01085
01086 }
else if (BreakToNone) {
01087
01088
01089
01090
01091
01092
01093
01094
01095
if ((OplockState ==
OplockIIGranted) ||
01096 (OplockFileObject != IrpSp->
FileObject)) {
01097
01098
Status =
FsRtlOplockBreakToNone( (
PNONOPAQUE_OPLOCK) *Oplock,
01099 IrpSp,
01100
Irp,
01101 Context,
01102 CompletionRoutine,
01103 PostIrpRoutine );
01104 }
01105 }
01106 }
01107 }
01108
01109
DebugTrace( -1,
Dbg,
"FsRtlCheckOplock: Exit -> %08lx\n",
Status );
01110
01111
return Status;
01112 }
01113
01114
01115 BOOLEAN
01116 FsRtlOplockIsFastIoPossible (
01117 IN POPLOCK Oplock
01118 )
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 {
01138 BOOLEAN FastIoPossible =
TRUE;
01139
01140
PAGED_CODE();
01141
01142
DebugTrace(+1,
Dbg,
"FsRtlOplockIsFastIoPossible: Oplock -> %08lx\n", *Oplock);
01143
01144
01145
01146
01147
01148
01149
01150
if (*Oplock !=
NULL) {
01151
01152
OPLOCK_STATE OplockState;
01153
01154 OplockState = ((
PNONOPAQUE_OPLOCK) *Oplock)->OplockState;
01155
01156
if (
FlagOn( OplockState,
LEVEL_II_OPLOCK |
OPLOCK_BREAK_MASK )) {
01157
01158 FastIoPossible =
FALSE;
01159 }
01160 }
01161
01162
DebugTrace(-1,
Dbg,
"FsRtlOplockIsFastIoPossible: Exit -> %08lx\n", FastIoPossible);
01163
01164
return FastIoPossible;
01165 }
01166
01167
01168 BOOLEAN
01169 FsRtlCurrentBatchOplock (
01170 IN POPLOCK Oplock
01171 )
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 {
01191 BOOLEAN BatchOplocks =
FALSE;
01192
01193
PAGED_CODE();
01194
01195
DebugTrace(+1,
Dbg,
"FsRtlCurrentBatchOplock: Oplock -> %08lx\n", *Oplock);
01196
01197
01198
01199
01200
01201
01202
01203
if ((*Oplock !=
NULL) &&
01204
FlagOn( ((
PNONOPAQUE_OPLOCK) *Oplock)->OplockState,
01205
BATCH_OPLOCK |
FILTER_OPLOCK )) {
01206
01207 BatchOplocks =
TRUE;
01208 }
01209
01210
DebugTrace(-1,
Dbg,
"FsRtlCurrentBatchOplock: Exit -> %08lx\n", BatchOplocks);
01211
01212
return BatchOplocks;
01213 }
01214
01215
01216
01217
01218
01219
01220
PNONOPAQUE_OPLOCK
01221 FsRtlAllocateOplock (
01222 )
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 {
01246
PNONOPAQUE_OPLOCK NewOplock =
NULL;
01247
01248
PAGED_CODE();
01249
01250
DebugTrace( +1,
Dbg,
"FsRtlAllocateOplock: Entered\n", 0);
01251
01252
01253
01254
01255
01256
try {
01257
01258
01259
01260
01261
01262
01263 NewOplock =
FsRtlpAllocatePool(
PagedPool,
sizeof(
NONOPAQUE_OPLOCK ));
01264
01265 RtlZeroMemory( NewOplock,
sizeof(
NONOPAQUE_OPLOCK ));
01266
01267 NewOplock->
FastMutex =
FsRtlpAllocatePool(
NonPagedPool,
sizeof(
FAST_MUTEX ));
01268
01269
ExInitializeFastMutex( NewOplock->
FastMutex );
01270
01271 InitializeListHead( &NewOplock->
IrpOplocksII );
01272 InitializeListHead( &NewOplock->
WaitingIrps );
01273
01274 NewOplock->
OplockState =
NoOplocksHeld;
01275
01276 } finally {
01277
01278
01279
01280
01281
01282
if (AbnormalTermination() && NewOplock !=
NULL) {
01283
01284
ExFreePool( NewOplock );
01285 }
01286
01287
DebugTrace(-1,
Dbg,
"GetOplockStructure: Exit -> %08lx\n", NewOplock);
01288 }
01289
01290
return NewOplock;
01291 }
01292
01293
01294
01295
01296
01297
01298
NTSTATUS
01299 FsRtlRequestExclusiveOplock (
01300 IN OUT PNONOPAQUE_OPLOCK *Oplock,
01301 IN
PIO_STACK_LOCATION IrpSp,
01302 IN
PIRP Irp OPTIONAL,
01303 IN OPLOCK_STATE NextOplockState
01304 )
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 {
01340
NTSTATUS Status;
01341
01342
PNONOPAQUE_OPLOCK ThisOplock;
01343
01344 BOOLEAN AcquiredMutex;
01345 BOOLEAN BreakOpFilter =
FALSE;
01346
01347 PLIST_ENTRY Link;
01348
01349
DebugTrace( +1,
Dbg,
"FsRtlRequestExclusiveOplock: Entered\n", 0 );
01350
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
01351
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
01352
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
01353
DebugTrace( 0,
Dbg,
"BatchOplock -> %01x\n", BatchOplock );
01354
01355
01356
01357
01358
01359
01360
01361
01362
if (*Oplock ==
NULL) {
01363
01364
DebugTrace( 0,
01365
Dbg,
01366
"Oplock currently not allocated\n",
01367 0);
01368
01369 ThisOplock =
FsRtlAllocateOplock();
01370 *Oplock = ThisOplock;
01371
01372 }
else {
01373
01374 ThisOplock = *Oplock;
01375 }
01376
01377
01378
01379
01380
01381
ExAcquireFastMutexUnsafe( ThisOplock->
FastMutex );
01382
01383 AcquiredMutex =
TRUE;
01384
01385
01386
01387
01388
01389
try {
01390
01391
01392
01393
01394
01395
01396
01397
if (NextOplockState ==
OpFilterReqPending) {
01398
01399
ASSERT(
FlagOn( ThisOplock->
OplockState,
NO_OPLOCK |
PENDING ));
01400
01401 ThisOplock->
IrpExclusiveOplock =
Irp;
01402 ThisOplock->
FileObject = IrpSp->FileObject;
01403
01404 ThisOplock->
OplockState =
OpFilterReqPending;
01405
Status = STATUS_SUCCESS;
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 }
else if (
FlagOn( ThisOplock->
OplockState,
01420
LEVEL_II_OPLOCK |
NO_OPLOCK |
PENDING )) {
01421
01422
PFAST_MUTEX OplockFastMutex;
01423
01424
if (ThisOplock->
OplockState ==
OplockIIGranted) {
01425
01426
ASSERT( ThisOplock->
IrpOplocksII.Flink == ThisOplock->
IrpOplocksII.Blink );
01427
01428
FsRtlRemoveAndCompleteIrp( ThisOplock->
IrpOplocksII.Flink );
01429 }
01430
01431
01432
01433
01434
01435 OplockFastMutex = ThisOplock->
FastMutex;
01436
01437
01438
01439
01440
01441
01442 ThisOplock->
IrpExclusiveOplock =
Irp;
01443 ThisOplock->
FileObject = IrpSp->FileObject;
01444 ThisOplock->
OplockState = NextOplockState;
01445
01446
IoMarkIrpPending(
Irp );
01447
01448
ObReferenceObject( IrpSp->FileObject );
01449
01450
Irp->
IoStatus.Information = (ULONG_PTR) ThisOplock;
01451
01452
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
01453
01454
01455
01456
01457
01458
01459
01460
if (
Irp->
Cancel) {
01461
01462 AcquiredMutex =
FALSE;
01463
01464
ExReleaseFastMutexUnsafe( OplockFastMutex );
01465
01466
FsRtlCancelExclusiveIrp(
NULL,
Irp );
01467
01468 }
else {
01469
01470
IoSetCancelRoutine(
Irp,
FsRtlCancelExclusiveIrp );
01471
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
01472 }
01473
01474
Status = STATUS_PENDING;
01475
01476 }
else {
01477
01478
01479
01480
01481
01482
01483
if (ARGUMENT_PRESENT(
Irp )) {
01484
01485
FsRtlCompleteRequest(
Irp, STATUS_OPLOCK_NOT_GRANTED );
01486 }
01487
01488
Status = STATUS_OPLOCK_NOT_GRANTED;
01489 }
01490
01491 } finally {
01492
01493
01494
01495
01496
01497
if (AcquiredMutex) {
01498
01499
ExReleaseFastMutexUnsafe( ThisOplock->
FastMutex );
01500 }
01501
01502
DebugTrace( +1,
Dbg,
"FsRtlRequestExclusiveOplock: Exit\n", 0 );
01503 }
01504
01505
return Status;
01506 }
01507
01508
01509
01510
01511
01512
01513
NTSTATUS
01514 FsRtlRequestOplockII (
01515 IN OUT PNONOPAQUE_OPLOCK *Oplock,
01516 IN
PIO_STACK_LOCATION IrpSp,
01517 IN
PIRP Irp
01518 )
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545 {
01546
NTSTATUS Status;
01547
01548
PNONOPAQUE_OPLOCK ThisOplock;
01549
01550 BOOLEAN AcquiredMutex;
01551
01552
DebugTrace( +1,
Dbg,
"FsRtlRequestOplockII: Entered\n", 0 );
01553
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
01554
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
01555
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
01556
01557
01558
01559
01560
01561
01562
01563
01564
if (*Oplock ==
NULL) {
01565
01566
DebugTrace( 0,
01567
Dbg,
01568
"Oplock currently not allocated\n",
01569 0);
01570
01571 ThisOplock =
FsRtlAllocateOplock();
01572 *Oplock = ThisOplock;
01573
01574 }
else {
01575
01576 ThisOplock = *Oplock;
01577 }
01578
01579
01580
01581
01582
01583
ExAcquireFastMutexUnsafe( ThisOplock->
FastMutex );
01584
01585 AcquiredMutex =
TRUE;
01586
01587
01588
01589
01590
01591
try {
01592
01593
01594
01595
01596
01597
01598
if (
FlagOn( ThisOplock->
OplockState,
NO_OPLOCK |
LEVEL_II_OPLOCK )) {
01599
01600
PFAST_MUTEX OplockFastMutex = ThisOplock->
FastMutex;
01601
01602
01603
01604
01605
01606
01607
IoMarkIrpPending(
Irp );
01608
01609
Irp->
IoStatus.Status = STATUS_SUCCESS;
01610
01611 InsertHeadList( &ThisOplock->
IrpOplocksII,
01612 &
Irp->
Tail.Overlay.ListEntry );
01613
01614
Irp->
IoStatus.Information = (ULONG_PTR) ThisOplock;
01615
01616 ThisOplock->
OplockState =
OplockIIGranted;
01617
01618
ObReferenceObject( IrpSp->FileObject );
01619
01620
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
01621
01622
01623
01624
01625
01626
01627
01628
if (
Irp->
Cancel) {
01629
01630 AcquiredMutex =
FALSE;
01631
01632
ExReleaseFastMutexUnsafe( OplockFastMutex );
01633
01634
FsRtlCancelOplockIIIrp(
NULL,
Irp );
01635
01636 }
else {
01637
01638
IoSetCancelRoutine(
Irp,
FsRtlCancelOplockIIIrp );
01639
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
01640 }
01641
01642
Status = STATUS_PENDING;
01643
01644 }
else {
01645
01646
01647
01648
01649
01650
01651
FsRtlCompleteRequest(
Irp, STATUS_OPLOCK_NOT_GRANTED );
01652
Status = STATUS_OPLOCK_NOT_GRANTED;
01653 }
01654
01655 } finally {
01656
01657
01658
01659
01660
01661
if (AcquiredMutex) {
01662
01663
ExReleaseFastMutexUnsafe( ThisOplock->
FastMutex );
01664 }
01665
01666
DebugTrace( +1,
Dbg,
"FsRtlRequestOplockII: Exit\n", 0 );
01667 }
01668
01669
return Status;
01670 }
01671
01672
01673
01674
01675
01676
01677
NTSTATUS
01678 FsRtlAcknowledgeOplockBreak (
01679 IN OUT PNONOPAQUE_OPLOCK Oplock,
01680 IN
PIO_STACK_LOCATION IrpSp,
01681 IN
PIRP Irp,
01682 IN BOOLEAN GrantLevelII
01683 )
01684
01685
01686
01687
01688
01689
01690
01691
01692
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 {
01726
NTSTATUS Status;
01727
01728 BOOLEAN AcquiredMutex;
01729
01730
DebugTrace( +1,
Dbg,
"FsRtlAcknowledgeOplockBreak: Entered\n", 0 );
01731
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
01732
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
01733
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
01734
01735
01736
01737
01738
01739
01740
if (Oplock ==
NULL) {
01741
01742
FsRtlCompleteRequest(
Irp, STATUS_INVALID_OPLOCK_PROTOCOL );
01743
DebugTrace( -1,
Dbg,
"FsRtlAcknowledgeOplockBreak: Exit -> %08lx\n", STATUS_INVALID_OPLOCK_PROTOCOL );
01744
return STATUS_INVALID_OPLOCK_PROTOCOL;
01745 }
01746
01747
01748
01749
01750
01751
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
01752 AcquiredMutex =
TRUE;
01753
01754
01755
01756
01757
01758
try {
01759
01760 BOOLEAN DereferenceFileObject =
TRUE;
01761
01762
01763
01764
01765
01766
01767
01768
if (Oplock->FileObject != IrpSp->FileObject) {
01769
01770
Status = STATUS_INVALID_OPLOCK_PROTOCOL;
01771
DebugTrace(0,
01772
Dbg,
01773
"Not oplock owner -> %08lx\n",
01774
Status);
01775
01776
FsRtlCompleteRequest(
Irp,
Status );
01777
try_return(
Status );
01778 }
01779
01780
01781
01782
01783
01784
01785
if (GrantLevelII &&
01786
FlagOn( Oplock->OplockState,
BREAK_TO_II )) {
01787
01788
PFAST_MUTEX OplockFastMutex = Oplock->FastMutex;
01789
01790
DebugTrace(0,
Dbg,
"OplockItoII\n", 0);
01791
01792
01793
01794
01795
01796
ASSERT( !
IoIsOperationSynchronous(
Irp ));
01797
01798
01799
01800
01801
01802
01803
01804
01805
IoMarkIrpPending(
Irp );
01806
01807
Irp->
IoStatus.Status = STATUS_SUCCESS;
01808
01809 InsertHeadList( &Oplock->IrpOplocksII,
01810 &
Irp->
Tail.Overlay.ListEntry );
01811
01812 DereferenceFileObject =
FALSE;
01813
01814 Oplock->OplockState =
OplockIIGranted;
01815
01816
Irp->
IoStatus.Information = (ULONG_PTR) Oplock;
01817
01818
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
01819
01820
01821
01822
01823
01824
01825
01826
if (
Irp->
Cancel) {
01827
01828 AcquiredMutex =
FALSE;
01829
01830
ExReleaseFastMutexUnsafe( OplockFastMutex );
01831
01832
FsRtlCancelOplockIIIrp(
NULL,
Irp );
01833
01834 }
else {
01835
01836
IoSetCancelRoutine(
Irp,
FsRtlCancelOplockIIIrp );
01837
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
01838 }
01839
01840
Status = STATUS_PENDING;
01841
01842
01843
01844
01845
01846
01847 }
else if (
FlagOn( Oplock->OplockState,
BREAK_TO_II |
BREAK_TO_NONE )) {
01848
01849
01850
01851
01852
01853
01854
DebugTrace(0,
Dbg,
"OplockItoNone\n", 0);
01855
01856
Status = STATUS_SUCCESS;
01857
FsRtlCompleteRequest(
Irp,
Status );
01858 Oplock->OplockState =
NoOplocksHeld;
01859
01860
01861
01862
01863
01864
01865
01866 }
else if (
FlagOn( Oplock->OplockState,
BREAK_TO_II_TO_NONE )) {
01867
01868
DebugTrace(0,
Dbg,
"AcknowledgeOplockBreak: OplockItoIItoNone\n", 0);
01869
01870
Status = STATUS_SUCCESS;
01871
Irp->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
01872
FsRtlCompleteRequest(
Irp,
Status );
01873 Oplock->OplockState =
NoOplocksHeld;
01874
01875 }
else {
01876
01877
Status = STATUS_INVALID_OPLOCK_PROTOCOL;
01878
DebugTrace(0,
01879
Dbg,
01880
"No break underway -> %08lx\n",
01881
Status);
01882
01883
FsRtlCompleteRequest(
Irp,
Status );
01884
try_return(
Status );
01885 }
01886
01887
01888
01889
01890
01891
while (!IsListEmpty( &Oplock->WaitingIrps )) {
01892
01893
PWAITING_IRP WaitingIrp;
01894
01895
01896
01897
01898
01899 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
01900
WAITING_IRP,
01901 Links );
01902
01903
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
01904 }
01905
01906
if (DereferenceFileObject) {
01907
01908
ObDereferenceObject( Oplock->FileObject );
01909 }
01910
01911 Oplock->FileObject =
NULL;
01912
01913 try_exit: NOTHING;
01914 } finally {
01915
01916
01917
01918
01919
01920
if (AcquiredMutex) {
01921
01922
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
01923 }
01924
01925
DebugTrace( -1,
Dbg,
"FsRtlAcknowledgeOplockBreak: Exit -> %08x\n",
Status );
01926 }
01927
01928
return Status;
01929 }
01930
01931
01932
01933
01934
01935
01936
NTSTATUS
01937 FsRtlOpBatchBreakClosePending (
01938 IN OUT PNONOPAQUE_OPLOCK Oplock,
01939 IN
PIO_STACK_LOCATION IrpSp,
01940 IN
PIRP Irp
01941 )
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968 {
01969
NTSTATUS Status = STATUS_SUCCESS;
01970
01971 BOOLEAN AcquiredMutex;
01972
01973
PAGED_CODE();
01974
01975
DebugTrace( +1,
Dbg,
"FsRtlOpBatchBreakClosePending: Entered\n", 0 );
01976
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
01977
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
01978
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
01979
01980
01981
01982
01983
01984
01985
if (Oplock ==
NULL) {
01986
01987
FsRtlCompleteRequest(
Irp, STATUS_INVALID_OPLOCK_PROTOCOL );
01988
DebugTrace( -1,
Dbg,
"FsRtlOpBatchClosePending: Exit -> %08lx\n", STATUS_INVALID_OPLOCK_PROTOCOL );
01989
return STATUS_INVALID_OPLOCK_PROTOCOL;
01990 }
01991
01992
01993
01994
01995
01996
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
01997 AcquiredMutex =
TRUE;
01998
01999
02000
02001
02002
02003
try {
02004
02005
02006
02007
02008
02009
02010
02011
if (Oplock->FileObject != IrpSp->FileObject) {
02012
02013
Status = STATUS_INVALID_OPLOCK_PROTOCOL;
02014
DebugTrace(0,
02015
Dbg,
02016
"Not oplock owner -> %08lx\n",
02017
Status);
02018
02019 }
else {
02020
02021
02022
02023
02024
02025
02026
02027
02028
if (
FlagOn( Oplock->OplockState,
02029
BREAK_TO_II |
BREAK_TO_NONE |
BREAK_TO_II_TO_NONE )) {
02030
02031
02032
02033
02034
02035
if (
FlagOn( Oplock->OplockState,
LEVEL_I_OPLOCK |
PENDING )) {
02036
02037
02038
02039
02040
02041
if (
FlagOn( Oplock->OplockState,
LEVEL_I_OPLOCK )) {
02042
02043
ObDereferenceObject( Oplock->FileObject );
02044 }
02045
02046 Oplock->OplockState =
NoOplocksHeld;
02047 Oplock->FileObject =
NULL;
02048
02049
while (!IsListEmpty( &Oplock->WaitingIrps )) {
02050
02051
PWAITING_IRP WaitingIrp;
02052
02053
02054
02055
02056
02057 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
02058
WAITING_IRP,
02059 Links );
02060
02061
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
02062 }
02063
02064
02065
02066
02067
02068
02069 }
else {
02070
02071
ClearFlag( Oplock->OplockState,
OPLOCK_BREAK_MASK );
02072
SetFlag( Oplock->OplockState,
CLOSE_PENDING );
02073 }
02074
02075 }
else {
02076
02077
Status = STATUS_INVALID_OPLOCK_PROTOCOL;
02078
DebugTrace(0,
02079
Dbg,
02080
"No break underway -> %08lx\n",
02081
Status);
02082 }
02083 }
02084
02085
02086
02087
02088
02089
FsRtlCompleteRequest(
Irp,
Status );
02090
02091 } finally {
02092
02093
02094
02095
02096
02097
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
02098
02099
DebugTrace(-1,
Dbg,
"FsRtlOpBatchBreakClosePending: Exit -> %08lx\n",
Status);
02100 }
02101
02102
return Status;
02103 }
02104
02105
02106
02107
02108
02109
02110
NTSTATUS
02111 FsRtlOplockBreakNotify (
02112 IN OUT PNONOPAQUE_OPLOCK Oplock,
02113 IN
PIO_STACK_LOCATION IrpSp,
02114 IN
PIRP Irp
02115 )
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145 {
02146
NTSTATUS Status;
02147
02148 BOOLEAN AcquiredMutex;
02149
02150
PAGED_CODE();
02151
02152
DebugTrace( +1,
Dbg,
"FsRtlOplockBreakNotify: Entered\n", 0 );
02153
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
02154
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
02155
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
02156
02157
02158
02159
02160
02161
if (Oplock ==
NULL) {
02162
02163
FsRtlCompleteRequest(
Irp, STATUS_SUCCESS );
02164
DebugTrace( -1,
Dbg,
"FsRtlOpBatchClosePending: Exit -> %08lx\n", STATUS_SUCCESS );
02165
return STATUS_SUCCESS;
02166 }
02167
02168
02169
02170
02171
02172
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
02173 AcquiredMutex =
TRUE;
02174
02175
02176
02177
02178
02179
try {
02180
02181
02182
02183
02184
02185
02186
if (!
FlagOn( Oplock->OplockState,
OPLOCK_BREAK_MASK )) {
02187
02188
DebugTrace(0,
02189
Dbg,
02190
"No exclusive oplock break underway\n",
02191 0);
02192
02193
FsRtlCompleteRequest(
Irp, STATUS_SUCCESS );
02194
try_return(
Status = STATUS_SUCCESS );
02195
02196 }
else if (
FlagOn( Oplock->OplockState,
PENDING )) {
02197
02198 Oplock->OplockState =
NoOplocksHeld;
02199 Oplock->FileObject =
NULL;
02200
02201
FsRtlCompleteRequest(
Irp, STATUS_SUCCESS );
02202
try_return(
Status = STATUS_SUCCESS );
02203 }
02204
02205
02206
02207
02208
02209
02210 AcquiredMutex =
FALSE;
02211
02212
02213
02214
02215
02216
Irp->
IoStatus.Status = STATUS_SUCCESS;
02217
02218
Status =
FsRtlWaitOnIrp( Oplock,
02219
Irp,
02220
NULL,
02221
FsRtlNotifyCompletion,
02222
NULL,
02223
NULL );
02224
02225 try_exit: NOTHING;
02226 } finally {
02227
02228
02229
02230
02231
02232
if (AcquiredMutex) {
02233
02234
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
02235 }
02236
02237
DebugTrace( -1,
Dbg,
"FsRtlOplockBreakNotify: Exit -> %08lx\n",
Status );
02238 }
02239
02240
return Status;
02241 }
02242
02243
02244
02245
02246
02247
02248
VOID
02249 FsRtlOplockCleanup (
02250 IN OUT PNONOPAQUE_OPLOCK Oplock,
02251 IN
PIO_STACK_LOCATION IrpSp
02252 )
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 {
02282
DebugTrace( +1,
Dbg,
"FsRtlOplockCleanup: Entered\n", 0 );
02283
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
02284
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
02285
02286
02287
02288
02289
02290
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
02291
02292
02293
02294
02295
02296
try {
02297
02298
02299
02300
02301
02302
if (Oplock->OplockState ==
NoOplocksHeld) {
02303
02304
DebugTrace(0,
02305
Dbg,
02306
"No oplocks on file\n",
02307 0);
02308
02309
try_return( NOTHING );
02310 }
02311
02312
02313
02314
02315
02316
if (Oplock->OplockState ==
OplockIIGranted) {
02317
02318 PLIST_ENTRY Link;
02319
PIRP Irp;
02320
PIO_STACK_LOCATION NextIrpSp;
02321
02322
DebugTrace(0,
02323
Dbg,
02324
"File has level 2 oplocks\n",
02325 0);
02326
02327
for (Link = Oplock->IrpOplocksII.Flink;
02328 Link != &Oplock->IrpOplocksII;
02329 Link = Link->Flink) {
02330
02331
Irp = CONTAINING_RECORD( Link,
IRP, Tail.Overlay.ListEntry );
02332
02333 NextIrpSp =
IoGetCurrentIrpStackLocation(
Irp );
02334
02335
02336
02337
02338
02339
if (IrpSp->FileObject == NextIrpSp->
FileObject) {
02340
02341
02342
02343
02344
02345 Link = Link->Blink;
02346
02347
02348
02349
02350
FsRtlRemoveAndCompleteIrp( Link->Flink );
02351 }
02352 }
02353
02354
02355
02356
02357
02358
02359
if (IsListEmpty( &Oplock->IrpOplocksII )) {
02360
02361 Oplock->OplockState =
NoOplocksHeld;
02362 }
02363
02364
try_return( NOTHING );
02365 }
02366
02367
02368
02369
02370
02371
02372
if (IrpSp->FileObject == Oplock->FileObject) {
02373
02374
DebugTrace(0,
02375
Dbg,
02376
"Handle owns level 1 oplock\n",
02377 0);
02378
02379
02380
02381
02382
02383
02384
if (!
FlagOn( Oplock->OplockState,
OPLOCK_BREAK_MASK |
PENDING )) {
02385
02386
PIRP ExclusiveIrp = Oplock->IrpExclusiveOplock;
02387
02388
DebugTrace(0,
02389
Dbg,
02390
"Initiate oplock break\n",
02391 0);
02392
02393
IoAcquireCancelSpinLock( &ExclusiveIrp->
CancelIrql );
02394
02395
IoSetCancelRoutine( ExclusiveIrp,
NULL );
02396
IoReleaseCancelSpinLock( ExclusiveIrp->
CancelIrql );
02397
02398 ExclusiveIrp->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
02399
02400
FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
02401
02402 Oplock->IrpExclusiveOplock =
NULL;
02403 }
02404
02405
02406
02407
02408
02409
02410
if (!
FlagOn( Oplock->OplockState,
PENDING )) {
02411
02412
ObDereferenceObject( IrpSp->FileObject );
02413 }
02414
02415 Oplock->FileObject =
NULL;
02416 Oplock->OplockState =
NoOplocksHeld;
02417
02418
while (!IsListEmpty( &Oplock->WaitingIrps )) {
02419
02420
PWAITING_IRP WaitingIrp;
02421
02422
02423
02424
02425
02426 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
02427
WAITING_IRP,
02428 Links );
02429
02430
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
02431 }
02432 }
02433
02434 try_exit: NOTHING;
02435 } finally {
02436
02437
02438
02439
02440
02441
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
02442
DebugTrace( +1,
Dbg,
"FsRtlOplockCleanup: Exit\n", 0 );
02443 }
02444
02445
return;
02446 }
02447
02448
02449
02450
02451
02452
02453
NTSTATUS
02454 FsRtlOplockBreakToII (
02455 IN OUT PNONOPAQUE_OPLOCK Oplock,
02456 IN
PIO_STACK_LOCATION IrpSp,
02457 IN
PIRP Irp,
02458 IN PVOID Context,
02459 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
02460 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine
02461 )
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
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
KEVENT Event;
02502
NTSTATUS Status;
02503
02504 BOOLEAN AcquiredMutex;
02505
02506
DebugTrace( +1,
Dbg,
"CheckOplockBreakToII: Entered\n", 0 );
02507
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
02508
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
02509
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
02510
02511
02512
02513
02514
02515
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
02516 AcquiredMutex =
TRUE;
02517
02518
02519
02520
02521
02522
try {
02523
02524
02525
02526
02527
02528
02529
if (!
FlagOn( Oplock->OplockState,
EXCLUSIVE )) {
02530
02531
DebugTrace(0,
02532
Dbg,
02533
"No oplocks or level II oplocks on file\n",
02534 0);
02535
02536
try_return(
Status = STATUS_SUCCESS );
02537 }
02538
02539
02540
02541
02542
02543
02544
02545
if (Oplock->FileObject == IrpSp->FileObject) {
02546
02547
DebugTrace(0,
02548
Dbg,
02549
"Handle owns level 1 oplock\n",
02550 0);
02551
02552
try_return(
Status = STATUS_SUCCESS );
02553 }
02554
02555
02556
02557
02558
02559
02560
if (!
FlagOn( Oplock->OplockState,
PENDING |
OPLOCK_BREAK_MASK )) {
02561
02562
PIRP IrpExclusive = Oplock->IrpExclusiveOplock;
02563
02564
DebugTrace(0,
02565
Dbg,
02566
"Breaking exclusive oplock\n",
02567 0);
02568
02569
IoAcquireCancelSpinLock( &IrpExclusive->
CancelIrql );
02570
IoSetCancelRoutine( IrpExclusive,
NULL );
02571
IoReleaseCancelSpinLock( IrpExclusive->
CancelIrql );
02572
02573
02574
02575
02576
02577
02578
if (IrpExclusive->
Cancel) {
02579
02580 IrpExclusive->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
02581
FsRtlCompleteRequest( IrpExclusive, STATUS_CANCELLED );
02582 Oplock->OplockState =
NoOplocksHeld;
02583 Oplock->IrpExclusiveOplock =
NULL;
02584
02585
ObDereferenceObject( Oplock->FileObject );
02586 Oplock->FileObject =
NULL;
02587
02588
02589
02590
02591
02592
while (!IsListEmpty( &Oplock->WaitingIrps )) {
02593
02594
PWAITING_IRP WaitingIrp;
02595
02596 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
02597
WAITING_IRP,
02598 Links );
02599
02600
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
02601 }
02602
02603
try_return(
Status = STATUS_SUCCESS );
02604
02605 }
else {
02606
02607
NTSTATUS CompletionStatus;
02608
02609
if (
FlagOn( Oplock->OplockState,
LEVEL_I_OPLOCK |
BATCH_OPLOCK )) {
02610
02611
SetFlag( Oplock->OplockState,
BREAK_TO_II );
02612 CompletionStatus = FILE_OPLOCK_BROKEN_TO_LEVEL_2;
02613
02614 }
else {
02615
02616
SetFlag( Oplock->OplockState,
BREAK_TO_NONE );
02617 CompletionStatus = FILE_OPLOCK_BROKEN_TO_NONE;
02618 }
02619
02620 Oplock->IrpExclusiveOplock->IoStatus.Information = CompletionStatus;
02621
FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
02622 Oplock->IrpExclusiveOplock =
NULL;
02623 }
02624
02625
02626
02627
02628
02629 }
else if (
FlagOn( Oplock->OplockState,
PENDING )) {
02630
02631 Oplock->OplockState =
NoOplocksHeld;
02632 Oplock->FileObject =
NULL;
02633
02634
try_return(
Status = STATUS_SUCCESS );
02635 }
02636
02637
02638
02639
02640
02641
02642
if ((IrpSp->MajorFunction ==
IRP_MJ_CREATE) &&
02643
FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
02644
02645
DebugTrace( 0,
Dbg,
"Don't block open\n", 0 );
02646
02647
try_return(
Status = STATUS_OPLOCK_BREAK_IN_PROGRESS );
02648 }
02649
02650
02651
02652
02653
02654
02655
02656
02657 AcquiredMutex =
FALSE;
02658
02659
Status =
FsRtlWaitOnIrp( Oplock,
02660
Irp,
02661 Context,
02662 CompletionRoutine,
02663 PostIrpRoutine,
02664 &
Event );
02665
02666 try_exit: NOTHING;
02667 } finally {
02668
02669
02670
02671
02672
02673
if (AcquiredMutex) {
02674
02675
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
02676 }
02677
02678
DebugTrace( -1,
Dbg,
"FsRtlOplockBreakToII: Exit -> %08lx\n",
Status );
02679 }
02680
02681
return Status;
02682 }
02683
02684
02685
02686
02687
02688
02689
NTSTATUS
02690 FsRtlOplockBreakToNone (
02691 IN OUT PNONOPAQUE_OPLOCK Oplock,
02692 IN
PIO_STACK_LOCATION IrpSp,
02693 IN
PIRP Irp,
02694 IN PVOID Context,
02695 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
02696 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL
02697 )
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736 {
02737
KEVENT Event;
02738
NTSTATUS Status;
02739
02740 BOOLEAN AcquiredMutex;
02741
02742
DebugTrace( +1,
Dbg,
"CheckOplockBreakToNone: Entered\n", 0 );
02743
DebugTrace( 0,
Dbg,
"Oplock -> %08lx\n", Oplock );
02744
DebugTrace( 0,
Dbg,
"IrpSp -> %08lx\n", IrpSp );
02745
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
02746
02747
02748
02749
02750
02751
ExAcquireFastMutexUnsafe( Oplock->FastMutex );
02752 AcquiredMutex =
TRUE;
02753
02754
02755
02756
02757
02758
try {
02759
02760
02761
02762
02763
02764
if (Oplock->OplockState ==
NoOplocksHeld) {
02765
02766
DebugTrace(0,
02767
Dbg,
02768
"No oplocks on file\n",
02769 0);
02770
02771
try_return(
Status = STATUS_SUCCESS );
02772 }
02773
02774
02775
02776
02777
02778
if (!
FlagOn( Oplock->OplockState,
02779
LEVEL_II_OPLOCK |
PENDING |
OPLOCK_BREAK_MASK )) {
02780
02781
PIRP IrpExclusive = Oplock->IrpExclusiveOplock;
02782
02783
DebugTrace(0,
02784
Dbg,
02785
"Breaking exclusive oplock\n",
02786 0);
02787
02788
IoAcquireCancelSpinLock( &IrpExclusive->
CancelIrql );
02789
IoSetCancelRoutine( IrpExclusive,
NULL );
02790
IoReleaseCancelSpinLock( IrpExclusive->
CancelIrql );
02791
02792
02793
02794
02795
02796
02797
if (IrpExclusive->
Cancel) {
02798
02799 IrpExclusive->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
02800
FsRtlCompleteRequest( IrpExclusive, STATUS_CANCELLED );
02801 Oplock->OplockState =
NoOplocksHeld;
02802 Oplock->IrpExclusiveOplock =
NULL;
02803
02804
ObDereferenceObject( Oplock->FileObject );
02805 Oplock->FileObject =
NULL;
02806
02807
02808
02809
02810
02811
while (!IsListEmpty( &Oplock->WaitingIrps )) {
02812
02813
PWAITING_IRP WaitingIrp;
02814
02815 WaitingIrp = CONTAINING_RECORD( Oplock->WaitingIrps.Flink,
02816
WAITING_IRP,
02817 Links );
02818
02819
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
02820 }
02821
02822
try_return(
Status = STATUS_SUCCESS );
02823
02824 }
else {
02825
02826 Oplock->IrpExclusiveOplock->IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
02827
FsRtlCompleteRequest( Oplock->IrpExclusiveOplock, STATUS_SUCCESS );
02828 Oplock->IrpExclusiveOplock =
NULL;
02829
02830
SetFlag( Oplock->OplockState,
BREAK_TO_NONE );
02831 }
02832
02833
02834
02835
02836
02837 }
else if (Oplock->OplockState ==
OplockIIGranted) {
02838
02839
DebugTrace(0,
02840
Dbg,
02841
"Breaking all level 2 oplocks\n",
02842 0);
02843
02844
while (!IsListEmpty( &Oplock->IrpOplocksII )) {
02845
02846
02847
02848
02849
02850
FsRtlRemoveAndCompleteIrp( Oplock->IrpOplocksII.Flink );
02851 }
02852
02853
02854
02855
02856
02857 Oplock->OplockState =
NoOplocksHeld;
02858
02859
try_return(
Status = STATUS_SUCCESS );
02860
02861
02862
02863
02864
02865
02866 }
else if (
FlagOn( Oplock->OplockState,
BREAK_TO_II )) {
02867
02868
ClearFlag( Oplock->OplockState,
BREAK_TO_II );
02869
SetFlag( Oplock->OplockState,
BREAK_TO_II_TO_NONE );
02870
02871
02872
02873
02874
02875 }
else if (
FlagOn( Oplock->OplockState,
PENDING )) {
02876
02877 Oplock->OplockState =
NoOplocksHeld;
02878 Oplock->FileObject =
NULL;
02879
02880
try_return(
Status = STATUS_SUCCESS );
02881 }
02882
02883
02884
02885
02886
02887
02888
02889
if (Oplock->FileObject == IrpSp->FileObject) {
02890
02891
DebugTrace(0,
02892
Dbg,
02893
"Handle owns level 1 oplock\n",
02894 0);
02895
02896
try_return(
Status = STATUS_SUCCESS );
02897 }
02898
02899
02900
02901
02902
02903
02904
if ((IrpSp->MajorFunction ==
IRP_MJ_CREATE) &&
02905
FlagOn( IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED )) {
02906
02907
DebugTrace( 0,
Dbg,
"Don't block open\n", 0 );
02908
02909
try_return(
Status = STATUS_OPLOCK_BREAK_IN_PROGRESS );
02910 }
02911
02912
02913
02914
02915
02916
02917
02918
02919 AcquiredMutex =
FALSE;
02920
02921
Status =
FsRtlWaitOnIrp( Oplock,
02922
Irp,
02923 Context,
02924 CompletionRoutine,
02925 PostIrpRoutine,
02926 &
Event );
02927
02928 try_exit: NOTHING;
02929 } finally {
02930
02931
02932
02933
02934
02935
if (AcquiredMutex) {
02936
02937
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
02938 }
02939
02940
DebugTrace( -1,
Dbg,
"CheckOplockBreakToNone: Exit -> %08lx\n",
Status );
02941 }
02942
02943
return Status;
02944 }
02945
02946
02947
02948
02949
02950
02951
VOID
02952 FsRtlRemoveAndCompleteIrp (
02953 IN PLIST_ENTRY Link
02954 )
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974 {
02975
PIRP Irp;
02976
PIO_STACK_LOCATION OplockIIIrpSp;
02977
02978
DebugTrace( +1,
Dbg,
"FsRtlRemoveAndCompleteIrp: Entered\n", 0 );
02979
02980
02981
02982
02983
02984
Irp = CONTAINING_RECORD( Link,
IRP, Tail.Overlay.ListEntry );
02985
02986
02987
02988
02989
02990 OplockIIIrpSp =
IoGetCurrentIrpStackLocation(
Irp );
02991
ObDereferenceObject( OplockIIIrpSp->
FileObject );
02992
02993
02994
02995
02996
02997
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
02998
02999
IoSetCancelRoutine(
Irp,
NULL );
03000
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03001
03002
03003
03004
03005
03006 RemoveEntryList( Link );
03007
03008
03009
03010
03011
03012
Irp->
IoStatus.Information = FILE_OPLOCK_BROKEN_TO_NONE;
03013
03014
FsRtlCompleteRequest(
Irp,
Irp->
Cancel ? STATUS_CANCELLED : STATUS_SUCCESS );
03015
03016
DebugTrace( -1,
Dbg,
"FsRtlRemoveAndCompleteIrp: Exit\n", 0 );
03017 }
03018
03019
03020
03021
03022
03023
03024
NTSTATUS
03025 FsRtlWaitOnIrp (
03026 IN OUT PNONOPAQUE_OPLOCK Oplock,
03027 IN
PIRP Irp,
03028 IN PVOID Context,
03029 IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL,
03030 IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL,
03031 IN
PKEVENT Event
03032 )
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076 {
03077 BOOLEAN AcquiredMutex;
03078
NTSTATUS Status;
03079
03080
PWAITING_IRP WaitingIrp;
03081
03082
DebugTrace( +1,
Dbg,
"FsRtlWaitOnIrp: Entered\n", 0 );
03083
03084
03085
03086
03087
03088 AcquiredMutex =
TRUE;
03089
03090
03091
03092
03093
03094
try {
03095
03096
PFAST_MUTEX OplockFastMutex = Oplock->FastMutex;
03097
03098
03099
03100
03101
03102 WaitingIrp =
FsRtlpAllocatePool(
PagedPool,
sizeof(
WAITING_IRP ));
03103
03104 WaitingIrp->
Irp =
Irp;
03105
03106 WaitingIrp->
Context = Context;
03107 WaitingIrp->
Information = (ULONG)
Irp->
IoStatus.Information;
03108
03109
03110
03111
03112
03113
03114
if (ARGUMENT_PRESENT( CompletionRoutine )) {
03115
03116 WaitingIrp->
CompletionRoutine = CompletionRoutine;
03117 WaitingIrp->
Context = Context;
03118
03119 }
else {
03120
03121 WaitingIrp->
CompletionRoutine =
FsRtlCompletionRoutinePriv;
03122 WaitingIrp->
Context =
Event;
03123
03124
KeInitializeEvent(
Event, NotificationEvent,
FALSE );
03125 }
03126
03127
03128
03129
03130
03131
if (ARGUMENT_PRESENT( PostIrpRoutine )) {
03132
03133 PostIrpRoutine( Context,
Irp );
03134 }
03135
03136
03137
03138
03139
03140
Irp->
IoStatus.Status = STATUS_SUCCESS;
03141
03142
03143
03144
03145
03146 InsertTailList( &Oplock->WaitingIrps, &WaitingIrp->
Links );
03147
03148
03149
03150
03151
03152
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
03153
Irp->
IoStatus.Information = (ULONG_PTR) Oplock;
03154
03155
03156
03157
03158
03159
03160
if (
Irp->
Cancel) {
03161
03162
ExReleaseFastMutexUnsafe( OplockFastMutex );
03163 AcquiredMutex =
FALSE;
03164
03165
if (ARGUMENT_PRESENT( CompletionRoutine )) {
03166
03167
IoMarkIrpPending(
Irp );
03168
Status = STATUS_PENDING;
03169
03170 }
else {
03171
03172
Status = STATUS_CANCELLED;
03173 }
03174
03175
FsRtlCancelWaitIrp(
NULL,
Irp );
03176
03177
03178
03179
03180
03181
03182 }
else {
03183
03184
IoSetCancelRoutine(
Irp,
FsRtlCancelWaitIrp );
03185
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03186
03187
03188
03189
03190
03191
03192
if (!ARGUMENT_PRESENT( CompletionRoutine )) {
03193
03194 AcquiredMutex =
FALSE;
03195
03196
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
03197
03198
KeWaitForSingleObject(
Event,
03199
Executive,
03200
KernelMode,
03201
FALSE,
03202
NULL );
03203
03204
Status =
Irp->
IoStatus.Status;
03205
03206
03207
03208
03209
03210 }
else {
03211
03212
IoMarkIrpPending(
Irp );
03213
03214
Status = STATUS_PENDING;
03215 }
03216 }
03217
03218 } finally {
03219
03220
03221
03222
03223
03224
if (AcquiredMutex) {
03225
03226
ExReleaseFastMutexUnsafe( Oplock->FastMutex );
03227 }
03228
03229
DebugTrace( -1,
Dbg,
"FsRtlWaitOnIrp: Exit\n", 0 );
03230 }
03231
03232
return Status;
03233 }
03234
03235
03236
03237
03238
03239
03240
VOID
03241 FsRtlCompletionRoutinePriv (
03242 IN PVOID Context,
03243 IN
PIRP Irp
03244 )
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268 {
03269
PAGED_CODE();
03270
03271
DebugTrace( +1,
Dbg,
"FsRtlCompletionRoutinePriv: Entered\n", 0 );
03272
03273
KeSetEvent( (
PKEVENT)Context, 0,
FALSE );
03274
03275
DebugTrace( -1,
Dbg,
"FsRtlCompletionRoutinePriv: Exit\n", 0 );
03276
03277
return;
03278
03279 UNREFERENCED_PARAMETER(
Irp );
03280 }
03281
03282
03283
03284
03285
03286
03287
VOID
03288 FsRtlCancelWaitIrp (
03289 IN
PDEVICE_OBJECT DeviceObject,
03290 IN
PIRP Irp
03291 )
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316 {
03317
PNONOPAQUE_OPLOCK Oplock;
03318
03319 PLIST_ENTRY Links;
03320
03321
DebugTrace( +1,
Dbg,
"FsRtlCancelWaitIrp: Entered\n", 0 );
03322
03323 Oplock = (
PNONOPAQUE_OPLOCK)
Irp->
IoStatus.Information;
03324
03325
03326
03327
03328
03329
IoSetCancelRoutine(
Irp,
NULL );
03330
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03331
03332
03333
03334
03335
03336
03337 ExAcquireFastMutex( Oplock->
FastMutex );
03338
03339
try {
03340
03341
for (Links = Oplock->
WaitingIrps.Flink;
03342 Links != &Oplock->
WaitingIrps;
03343 Links = Links->Flink ) {
03344
03345
PWAITING_IRP WaitingIrp;
03346
03347
03348
03349
03350
03351 WaitingIrp = CONTAINING_RECORD( Links,
WAITING_IRP, Links );
03352
03353
DebugTrace(0,
Dbg,
"FsRtlCancelWaitIrp, Loop top, WaitingIrp = %08lx\n", WaitingIrp);
03354
03355
03356
03357
03358
03359
if (WaitingIrp->
Irp->
Cancel) {
03360
03361
03362
03363
03364
03365
03366
03367
03368 Links = Links->Blink;
03369
03370
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
03371 }
03372 }
03373
03374 } finally {
03375
03376
03377
03378
03379
03380 ExReleaseFastMutex( Oplock->
FastMutex );
03381
03382
DebugTrace( -1,
Dbg,
"FsRtlCancelWaitIrp: Exit\n", 0 );
03383 }
03384
03385
return;
03386
03387 UNREFERENCED_PARAMETER( DeviceObject );
03388 }
03389
03390
03391
03392
03393
03394
03395
VOID
03396 FsRtlCancelOplockIIIrp (
03397 IN
PDEVICE_OBJECT DeviceObject,
03398 IN
PIRP Irp
03399 )
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424 {
03425
PNONOPAQUE_OPLOCK Oplock;
03426 BOOLEAN LevelIIIrps;
03427
03428 PLIST_ENTRY Links;
03429
03430
DebugTrace( +1,
Dbg,
"FsRtlCancelOplockIIIrp: Entered\n", 0 );
03431
03432 Oplock = (
PNONOPAQUE_OPLOCK)
Irp->
IoStatus.Information;
03433
03434
03435
03436
03437
03438
IoSetCancelRoutine(
Irp,
NULL );
03439
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03440
03441 LevelIIIrps =
FALSE;
03442
03443
03444
03445
03446
03447
03448 ExAcquireFastMutex( Oplock->
FastMutex );
03449
03450
try {
03451
03452
for (Links = Oplock->
IrpOplocksII.Flink;
03453 Links != &Oplock->
IrpOplocksII;
03454 Links = Links->Flink ) {
03455
03456
PIRP OplockIIIrp;
03457
03458
03459
03460
03461
03462 OplockIIIrp = CONTAINING_RECORD( Links,
IRP, Tail.Overlay.ListEntry );
03463
03464
DebugTrace(0,
Dbg,
"FsRtlCancelOplockIIIrp, Loop top, Irp = %08lx\n", OplockIIIrp);
03465
03466
03467
03468
03469
03470
if (OplockIIIrp->
Cancel) {
03471
03472
03473
03474
03475
03476
03477
03478
03479 Links = Links->Blink;
03480
03481
FsRtlRemoveAndCompleteIrp( Links->Flink );
03482
03483 LevelIIIrps =
TRUE;
03484 }
03485 }
03486
03487
03488
03489
03490
03491
03492
if (LevelIIIrps && IsListEmpty( &Oplock->
IrpOplocksII )) {
03493
03494 Oplock->
OplockState =
NoOplocksHeld;
03495 }
03496
03497 } finally {
03498
03499
03500
03501
03502
03503 ExReleaseFastMutex( Oplock->
FastMutex );
03504
03505
DebugTrace( -1,
Dbg,
"FsRtlCancelOplockIIIrp: Exit\n", 0 );
03506 }
03507
03508
return;
03509
03510 UNREFERENCED_PARAMETER( DeviceObject );
03511 }
03512
03513
03514
03515
03516
03517
03518
VOID
03519 FsRtlCancelExclusiveIrp (
03520 IN
PDEVICE_OBJECT DeviceObject,
03521 IN
PIRP Irp
03522 )
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544 {
03545
PNONOPAQUE_OPLOCK Oplock;
03546
03547
DebugTrace( +1,
Dbg,
"FsRtlCancelExclusiveIrp: Entered\n", 0 );
03548
03549 Oplock = (
PNONOPAQUE_OPLOCK)
Irp->
IoStatus.Information;
03550
03551
03552
03553
03554
03555
IoSetCancelRoutine(
Irp,
NULL );
03556
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03557
03558
03559
03560
03561
03562 ExAcquireFastMutex( Oplock->
FastMutex );
03563
03564
try {
03565
03566
03567
03568
03569
03570
03571
if ((Oplock->
IrpExclusiveOplock !=
NULL) &&
03572 (Oplock->
IrpExclusiveOplock->
Cancel)) {
03573
03574
FsRtlCompleteRequest( Oplock->
IrpExclusiveOplock, STATUS_CANCELLED );
03575 Oplock->
IrpExclusiveOplock =
NULL;
03576
03577
ObDereferenceObject( Oplock->
FileObject );
03578 Oplock->
FileObject =
NULL;
03579 Oplock->
OplockState =
NoOplocksHeld;
03580
03581
03582
03583
03584
03585
while (!IsListEmpty( &Oplock->
WaitingIrps )) {
03586
03587
PWAITING_IRP WaitingIrp;
03588
03589
03590
03591
03592
03593 WaitingIrp = CONTAINING_RECORD( Oplock->
WaitingIrps.Flink,
03594
WAITING_IRP,
03595 Links );
03596
03597
FsRtlRemoveAndCompleteWaitIrp( WaitingIrp );
03598 }
03599 }
03600
03601 } finally {
03602
03603
03604
03605
03606
03607 ExReleaseFastMutex( Oplock->
FastMutex );
03608
03609
DebugTrace( -1,
Dbg,
"FsRtlCancelExclusiveIrp: Exit\n", 0 );
03610 }
03611
03612
return;
03613
03614 UNREFERENCED_PARAMETER( DeviceObject );
03615 }
03616
03617
03618
03619
03620
03621
03622
VOID
03623 FsRtlRemoveAndCompleteWaitIrp (
03624 IN PWAITING_IRP WaitingIrp
03625 )
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645 {
03646
PIRP Irp;
03647
03648
PAGED_CODE();
03649
03650
DebugTrace( +1,
Dbg,
"FsRtlRemoveAndCompleteWaitIrp: Entered\n", 0 );
03651
03652
03653
03654
03655
03656 RemoveEntryList( &WaitingIrp->Links );
03657
03658
Irp = WaitingIrp->Irp;
03659
03660
IoAcquireCancelSpinLock( &
Irp->
CancelIrql );
03661
03662
IoSetCancelRoutine(
Irp,
NULL );
03663
IoReleaseCancelSpinLock(
Irp->
CancelIrql );
03664
03665
03666
03667
03668
03669
Irp->
IoStatus.Information = WaitingIrp->Information;
03670
03671
Irp->
IoStatus.Status = (
Irp->
Cancel
03672 ? STATUS_CANCELLED
03673 : STATUS_SUCCESS);
03674
03675
03676
03677
03678
03679 WaitingIrp->CompletionRoutine( WaitingIrp->Context,
Irp );
03680
03681
03682
03683
03684
03685
ExFreePool( WaitingIrp );
03686
03687
DebugTrace( -1,
Dbg,
"FsRtlRemoveAndCompleteWaitIrp: Exit\n", 0 );
03688
03689
return;
03690 }
03691
03692
03693
03694
03695
03696
03697
VOID
03698 FsRtlNotifyCompletion (
03699 IN PVOID Context,
03700 IN
PIRP Irp
03701 )
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723 {
03724
PAGED_CODE();
03725
03726
DebugTrace( +1,
Dbg,
"FsRtlNotifyCompletion: Entered\n", 0 );
03727
03728
03729
03730
03731
03732
FsRtlCompleteRequest(
Irp,
Irp->
IoStatus.Status );
03733
03734
DebugTrace( -1,
Dbg,
"FsRtlNotifyCompletion: Exit\n", 0 );
03735
03736
return;
03737 }