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
#include "FsRtlP.h"
00062
00063
00064
00065
00066
00067 #define Dbg (0x04000000)
00068
00069
00070
00071
00072
00073
00074 typedef struct _REAL_NOTIFY_SYNC {
00075
00076 FAST_MUTEX FastMutex;
00077 ERESOURCE_THREAD OwningThread;
00078 ULONG
OwnerCount;
00079
00080 }
REAL_NOTIFY_SYNC, *
PREAL_NOTIFY_SYNC;
00081
00082
00083
00084
00085
00086
00087 typedef struct _NOTIFY_CHANGE {
00088
00089
00090
00091
00092
00093
00094 PREAL_NOTIFY_SYNC NotifySync;
00095
00096
00097
00098
00099
00100
00101
00102
00103 PVOID
FsContext;
00104
00105
00106
00107
00108
00109
00110
00111 PVOID
StreamID;
00112
00113
00114
00115
00116
00117
00118
00119
00120 PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback;
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 PSECURITY_SUBJECT_CONTEXT SubjectContext;
00131
00132
00133
00134
00135
00136
00137
00138
00139 PSTRING
FullDirectoryName;
00140
00141
00142
00143
00144
00145
00146 LIST_ENTRY
NotifyList;
00147
00148
00149
00150
00151
00152
00153 LIST_ENTRY
NotifyIrps;
00154
00155
00156
00157
00158
00159 USHORT Flags;
00160
00161
00162
00163
00164
00165
00166 UCHAR
CharacterSize;
00167
00168
00169
00170
00171
00172
00173 ULONG
CompletionFilter;
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 PVOID
AllocatedBuffer;
00188 PVOID
Buffer;
00189 ULONG
BufferLength;
00190 ULONG
ThisBufferLength;
00191 ULONG
DataLength;
00192 ULONG
LastEntry;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 ULONG
ReferenceCount;
00204
00205
00206
00207
00208
00209
00210 PEPROCESS OwningProcess;
00211
00212 }
NOTIFY_CHANGE, *
PNOTIFY_CHANGE;
00213
00214 #define NOTIFY_WATCH_TREE (0x0001)
00215 #define NOTIFY_IMMEDIATE_NOTIFY (0x0002)
00216 #define NOTIFY_CLEANUP_CALLED (0x0004)
00217 #define NOTIFY_DEFER_NOTIFY (0x0008)
00218 #define NOTIFY_DIR_IS_ROOT (0x0010)
00219 #define NOTIFY_STREAM_IS_DELETED (0x0020)
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 #define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
00237
00238 #define PtrOffset(BASE,OFFSET) ((ULONG)((PCHAR)(OFFSET) - (PCHAR)(BASE)))
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 #define SetFlag(F,SF) { \
00255
(F) |= (SF); \
00256
}
00257
00258 #define ClearFlag(F,SF) { \
00259
(F) &= ~(SF); \
00260
}
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 #define AcquireNotifySync(NS) { \
00275
ERESOURCE_THREAD _CurrentThread; \
00276
_CurrentThread = (ERESOURCE_THREAD) PsGetCurrentThread(); \
00277
if (_CurrentThread != ((PREAL_NOTIFY_SYNC) (NS))->OwningThread) { \
00278
ExAcquireFastMutexUnsafe( &((PREAL_NOTIFY_SYNC) (NS))->FastMutex ); \
00279
((PREAL_NOTIFY_SYNC) (NS))->OwningThread = _CurrentThread; \
00280
} \
00281
((PREAL_NOTIFY_SYNC) (NS))->OwnerCount += 1; \
00282
}
00283
00284 #define ReleaseNotifySync(NS) { \
00285
((PREAL_NOTIFY_SYNC) (NS))->OwnerCount -= 1; \
00286
if (((PREAL_NOTIFY_SYNC) (NS))->OwnerCount == 0) { \
00287
((PREAL_NOTIFY_SYNC) (NS))->OwningThread = (ERESOURCE_THREAD) 0; \
00288
ExReleaseFastMutexUnsafe(&((PREAL_NOTIFY_SYNC) (NS))->FastMutex); \
00289
} \
00290
}
00291
00292
00293
00294
00295
00296
#undef MODULE_POOL_TAG
00297 #define MODULE_POOL_TAG ('NrSF')
00298
00299
00300
00301
00302
00303
00304
PNOTIFY_CHANGE
00305
FsRtlIsNotifyOnList (
00306 IN PLIST_ENTRY NotifyListHead,
00307 IN PVOID FsContext
00308 );
00309
00310
VOID
00311
FsRtlNotifyCompleteIrp (
00312 IN
PIRP NotifyIrp,
00313 IN PNOTIFY_CHANGE Notify,
00314 IN ULONG DataLength,
00315 IN NTSTATUS Status,
00316 IN ULONG CheckCancel
00317 );
00318
00319 BOOLEAN
00320
FsRtlNotifySetCancelRoutine (
00321 IN
PIRP NotifyIrp,
00322 IN PNOTIFY_CHANGE Notify OPTIONAL
00323 );
00324
00325 BOOLEAN
00326
FsRtlNotifyUpdateBuffer (
00327 IN PFILE_NOTIFY_INFORMATION NotifyInfo,
00328 IN ULONG FileAction,
00329 IN PSTRING ParentName,
00330 IN PSTRING TargetName,
00331 IN PSTRING StreamName OPTIONAL,
00332 IN BOOLEAN UnicodeName,
00333 IN ULONG SizeOfEntry
00334 );
00335
00336
VOID
00337
FsRtlNotifyCompleteIrpList (
00338 IN PNOTIFY_CHANGE Notify,
00339 IN NTSTATUS Status
00340 );
00341
00342
VOID
00343
FsRtlCancelNotify (
00344 IN
PDEVICE_OBJECT DeviceObject,
00345 IN
PIRP ThisIrp
00346 );
00347
00348
VOID
00349
FsRtlCheckNotifyForDelete (
00350 IN PLIST_ENTRY NotifyListHead,
00351 IN PVOID FsContext
00352 );
00353
00354
#ifdef ALLOC_PRAGMA
00355
#pragma alloc_text(PAGE, FsRtlNotifyInitializeSync)
00356
#pragma alloc_text(PAGE, FsRtlNotifyUninitializeSync)
00357
#pragma alloc_text(PAGE, FsRtlNotifyFullChangeDirectory)
00358
#pragma alloc_text(PAGE, FsRtlNotifyFullReportChange)
00359
#pragma alloc_text(PAGE, FsRtlIsNotifyOnList)
00360
#pragma alloc_text(PAGE, FsRtlNotifyChangeDirectory)
00361
#pragma alloc_text(PAGE, FsRtlNotifyCleanup)
00362
#pragma alloc_text(PAGE, FsRtlNotifyCompleteIrp)
00363
#pragma alloc_text(PAGE, FsRtlNotifyReportChange)
00364
#pragma alloc_text(PAGE, FsRtlNotifyUpdateBuffer)
00365
#pragma alloc_text(PAGE, FsRtlCheckNotifyForDelete)
00366
#endif
00367
00368
00369
NTKERNELAPI
00370
VOID
00371 FsRtlNotifyInitializeSync (
00372 IN PNOTIFY_SYNC *NotifySync
00373 )
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 {
00393
PREAL_NOTIFY_SYNC RealSync;
00394
00395
PAGED_CODE();
00396
00397
DebugTrace( +1,
Dbg,
"FsRtlNotifyInitializeSync: Entered\n", 0 );
00398
00399
00400
00401
00402
00403
00404 *NotifySync =
NULL;
00405
00406 RealSync = (
PREAL_NOTIFY_SYNC)
FsRtlpAllocatePool(
NonPagedPool,
00407
sizeof(
REAL_NOTIFY_SYNC ));
00408
00409
00410
00411
00412
00413
ExInitializeFastMutex( &RealSync->
FastMutex );
00414 RealSync->
OwningThread = (
ERESOURCE_THREAD) 0;
00415 RealSync->
OwnerCount = 0;
00416
00417 *NotifySync = (
PNOTIFY_SYNC) RealSync;
00418
00419
DebugTrace( -1,
Dbg,
"FsRtlNotifyInitializeSync: Exit\n", 0 );
00420
return;
00421 }
00422
00423
00424
NTKERNELAPI
00425
VOID
00426 FsRtlNotifyUninitializeSync (
00427 IN PNOTIFY_SYNC *NotifySync
00428 )
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 {
00449
PAGED_CODE();
00450
00451
DebugTrace( +1,
Dbg,
"FsRtlNotifyUninitializeSync: Entered\n", 0 );
00452
00453
00454
00455
00456
00457
if (*NotifySync !=
NULL) {
00458
00459
ExFreePool( *NotifySync );
00460 *NotifySync =
NULL;
00461 }
00462
00463
DebugTrace( -1,
Dbg,
"FsRtlNotifyUninitializeSync: Exit\n", 0 );
00464
return;
00465 }
00466
00467
00468
VOID
00469 FsRtlNotifyChangeDirectory (
00470 IN PNOTIFY_SYNC NotifySync,
00471 IN PVOID FsContext,
00472 IN PSTRING FullDirectoryName,
00473 IN PLIST_ENTRY NotifyList,
00474 IN BOOLEAN WatchTree,
00475 IN ULONG CompletionFilter,
00476 IN
PIRP NotifyIrp
00477 )
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 {
00521
PAGED_CODE();
00522
00523
DebugTrace( +1,
Dbg,
"FsRtlNotifyChangeDirectory: Entered\n", 0 );
00524
00525
00526
00527
00528
00529
FsRtlNotifyFullChangeDirectory( NotifySync,
00530 NotifyList,
00531 FsContext,
00532 FullDirectoryName,
00533
WatchTree,
00534
TRUE,
00535 CompletionFilter,
00536 NotifyIrp,
00537
NULL,
00538
NULL );
00539
00540
DebugTrace( -1,
Dbg,
"FsRtlNotifyChangeDirectory: Exit\n", 0 );
00541
00542
return;
00543 }
00544
00545
00546
VOID
00547 FsRtlNotifyFullChangeDirectory (
00548 IN PNOTIFY_SYNC NotifySync,
00549 IN PLIST_ENTRY NotifyList,
00550 IN PVOID FsContext,
00551 IN PSTRING FullDirectoryName,
00552 IN BOOLEAN WatchTree,
00553 IN BOOLEAN IgnoreBuffer,
00554 IN ULONG CompletionFilter,
00555 IN
PIRP NotifyIrp,
00556 IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL,
00557 IN
PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL
00558 )
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
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 {
00625
PNOTIFY_CHANGE Notify;
00626
PIO_STACK_LOCATION IrpSp;
00627
00628
PAGED_CODE();
00629
00630
DebugTrace( +1,
Dbg,
"FsRtlNotifyFullChangeDirectory: Entered\n", 0 );
00631
00632
00633
00634
00635
00636
AcquireNotifySync( NotifySync );
00637
00638
00639
00640
00641
00642
try {
00643
00644
00645
00646
00647
00648
00649
if (NotifyIrp ==
NULL) {
00650
00651
FsRtlCheckNotifyForDelete( NotifyList, FsContext );
00652
try_return( NOTHING );
00653 }
00654
00655
00656
00657
00658
00659 IrpSp =
IoGetCurrentIrpStackLocation( NotifyIrp );
00660
00661
00662
00663
00664
00665 NotifyIrp->IoStatus.Status = STATUS_SUCCESS;
00666 NotifyIrp->IoStatus.Information = 0;
00667
00668
00669
00670
00671
00672
00673
if (
FlagOn( IrpSp->
FileObject->
Flags,
FO_CLEANUP_COMPLETE )) {
00674
00675
00676
00677
00678
00679
IoMarkIrpPending( NotifyIrp );
00680
00681
FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_CLEANUP );
00682
try_return( NOTHING );
00683 }
00684
00685
00686
00687
00688
00689
00690 Notify =
FsRtlIsNotifyOnList( NotifyList, FsContext );
00691
00692
if (Notify ==
NULL) {
00693
00694
00695
00696
00697
00698 Notify =
FsRtlpAllocatePool(
PagedPool,
sizeof(
NOTIFY_CHANGE ));
00699 RtlZeroMemory( Notify,
sizeof(
NOTIFY_CHANGE ));
00700
00701 Notify->
NotifySync = (
PREAL_NOTIFY_SYNC) NotifySync;
00702 Notify->
FsContext = FsContext;
00703 Notify->
StreamID = IrpSp->
FileObject->
FsContext;
00704
00705 Notify->
TraverseCallback = TraverseCallback;
00706 Notify->
SubjectContext = SubjectContext;
00707 SubjectContext =
NULL;
00708
00709 Notify->
FullDirectoryName = FullDirectoryName;
00710
00711 InitializeListHead( &Notify->
NotifyIrps );
00712
00713
if (
WatchTree) {
00714
00715
SetFlag( Notify->
Flags,
NOTIFY_WATCH_TREE );
00716 }
00717
00718
if (FullDirectoryName ==
NULL) {
00719
00720
00721
00722
00723
00724
00725 Notify->
CharacterSize =
sizeof(
CHAR );
00726
00727 }
else {
00728
00729
00730
00731
00732
00733
00734
if (FullDirectoryName->Length >= 2
00735 && FullDirectoryName->Buffer[1] ==
'\0') {
00736
00737 Notify->
CharacterSize =
sizeof( WCHAR );
00738
00739 }
else {
00740
00741 Notify->
CharacterSize =
sizeof(
CHAR );
00742 }
00743
00744
if (FullDirectoryName->Length == Notify->
CharacterSize) {
00745
00746
SetFlag( Notify->
Flags,
NOTIFY_DIR_IS_ROOT );
00747 }
00748 }
00749
00750 Notify->
CompletionFilter = CompletionFilter;
00751
00752
00753
00754
00755
00756
00757
if (!IgnoreBuffer) {
00758
00759 Notify->
BufferLength = IrpSp->
Parameters.NotifyDirectory.Length;
00760 }
00761
00762 Notify->
OwningProcess =
THREAD_TO_PROCESS( NotifyIrp->Tail.Overlay.Thread );
00763 InsertTailList( NotifyList, &Notify->
NotifyList );
00764
00765 Notify->
ReferenceCount = 1;
00766
00767
00768
00769
00770
00771
00772 }
else if (
FlagOn( Notify->
Flags,
NOTIFY_CLEANUP_CALLED )) {
00773
00774
00775
00776
00777
00778
IoMarkIrpPending( NotifyIrp );
00779
00780
FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_CLEANUP );
00781
try_return( NOTHING );
00782
00783
00784
00785
00786
00787 }
else if (
FlagOn( Notify->
Flags,
NOTIFY_STREAM_IS_DELETED )) {
00788
00789
00790
00791
00792
00793
IoMarkIrpPending( NotifyIrp );
00794
00795
FsRtlCompleteRequest( NotifyIrp, STATUS_DELETE_PENDING );
00796
try_return( NOTHING );
00797
00798
00799
00800
00801
00802
00803 }
else if (
FlagOn( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY )
00804 && !
FlagOn( Notify->
Flags,
NOTIFY_DEFER_NOTIFY )) {
00805
00806
DebugTrace( 0,
Dbg,
"Notify has been pending\n", 0 );
00807
00808
00809
00810
00811
00812
00813
00814
ClearFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
00815
00816
00817
00818
00819
00820
IoMarkIrpPending( NotifyIrp );
00821
00822
FsRtlCompleteRequest( NotifyIrp, STATUS_NOTIFY_ENUM_DIR );
00823
try_return( NOTHING );
00824
00825 }
else if (Notify->
DataLength != 0
00826 && !
FlagOn( Notify->
Flags,
NOTIFY_DEFER_NOTIFY )) {
00827
00828 ULONG ThisDataLength = Notify->
DataLength;
00829
00830
00831
00832
00833
00834 Notify->
DataLength = 0;
00835 Notify->
LastEntry = 0;
00836
00837
FsRtlNotifyCompleteIrp( NotifyIrp,
00838 Notify,
00839 ThisDataLength,
00840 STATUS_SUCCESS,
00841
FALSE );
00842
00843
try_return( NOTHING );
00844 }
00845
00846
00847
00848
00849
00850 NotifyIrp->IoStatus.Information = (ULONG_PTR) Notify;
00851
IoMarkIrpPending( NotifyIrp );
00852 InsertTailList( &Notify->
NotifyIrps, &NotifyIrp->Tail.Overlay.ListEntry );
00853
00854
00855
00856
00857
00858 InterlockedIncrement( &Notify->
ReferenceCount );
00859
00860
00861
00862
00863
00864
FsRtlNotifySetCancelRoutine( NotifyIrp,
NULL );
00865
00866 try_exit: NOTHING;
00867 } finally {
00868
00869
00870
00871
00872
00873
ReleaseNotifySync( NotifySync );
00874
00875
00876
00877
00878
00879
00880
00881
00882
if ((SubjectContext !=
NULL) &&
00883 (Notify->
FullDirectoryName !=
NULL)) {
00884
00885
SeReleaseSubjectContext( SubjectContext );
00886
ExFreePool( SubjectContext );
00887 }
00888
00889
DebugTrace( -1,
Dbg,
"FsRtlNotifyFullChangeDirectory: Exit\n", 0 );
00890 }
00891
00892
return;
00893 }
00894
00895
00896
VOID
00897 FsRtlNotifyReportChange (
00898 IN PNOTIFY_SYNC NotifySync,
00899 IN PLIST_ENTRY NotifyList,
00900 IN PSTRING FullTargetName,
00901 IN PSTRING TargetName,
00902 IN ULONG FilterMatch
00903 )
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 {
00948
PAGED_CODE();
00949
00950
DebugTrace( +1,
Dbg,
"FsRtlNotifyReportChange: Entered\n", 0 );
00951
00952
00953
00954
00955
00956
FsRtlNotifyFullReportChange( NotifySync,
00957 NotifyList,
00958 FullTargetName,
00959 (
USHORT) (FullTargetName->Length - TargetName->Length),
00960
NULL,
00961
NULL,
00962 FilterMatch,
00963 0,
00964
NULL );
00965
00966
DebugTrace( -1,
Dbg,
"FsRtlNotifyReportChange: Exit\n", 0 );
00967
00968
return;
00969 }
00970
00971
00972
VOID
00973 FsRtlNotifyFullReportChange (
00974 IN PNOTIFY_SYNC NotifySync,
00975 IN PLIST_ENTRY NotifyList,
00976 IN PSTRING FullTargetName,
00977 IN USHORT TargetNameOffset,
00978 IN PSTRING StreamName OPTIONAL,
00979 IN PSTRING NormalizedParentName OPTIONAL,
00980 IN ULONG FilterMatch,
00981 IN ULONG Action,
00982 IN PVOID TargetContext
00983 )
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
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
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 {
01040 PLIST_ENTRY NotifyLinks;
01041
01042 STRING NormalizedParent;
01043 STRING ParentName;
01044 STRING TargetName;
01045
01046
PNOTIFY_CHANGE Notify;
01047 STRING TargetParent;
01048
PIRP NotifyIrp;
01049
01050 BOOLEAN NotifyIsParent;
01051 BOOLEAN ViewIndex =
FALSE;
01052 UCHAR ComponentCount;
01053 ULONG SizeOfEntry;
01054 ULONG CurrentOffset;
01055 ULONG NextEntryOffset;
01056 ULONG ExceptionCode;
01057
01058
PAGED_CODE();
01059
01060
DebugTrace( +1,
Dbg,
"FsRtlNotifyFullReportChange: Entered\n", 0 );
01061
01062
01063
01064
01065
01066
if ((TargetNameOffset == 0) && (FullTargetName !=
NULL)) {
01067
01068
DebugTrace( -1,
Dbg,
"FsRtlNotifyFullReportChange: Exit\n", 0 );
01069
return;
01070 }
01071
01072 ParentName.Buffer =
NULL;
01073 TargetName.Buffer =
NULL;
01074
01075
01076
01077
01078
01079
AcquireNotifySync( NotifySync );
01080
01081
01082
01083
01084
01085
try {
01086
01087
01088
01089
01090
01091
for (NotifyLinks = NotifyList->Flink;
01092 NotifyLinks != NotifyList;
01093 NotifyLinks = NotifyLinks->Flink) {
01094
01095
01096
01097
01098
01099 Notify = CONTAINING_RECORD( NotifyLinks,
NOTIFY_CHANGE, NotifyList );
01100
01101
01102
01103
01104
01105
01106
if (FullTargetName ==
NULL) {
01107
01108
ASSERTMSG(
"Directory notify handle in view index notify list!", Notify->
FullDirectoryName ==
NULL);
01109
01110
01111
01112
01113
01114
if (TargetContext != Notify->
SubjectContext) {
01115
01116
continue;
01117 }
01118
01119 TargetParent.Buffer =
NULL;
01120 TargetParent.Length = 0;
01121
01122 ViewIndex =
TRUE;
01123
01124
01125
01126
01127
01128 }
else {
01129
01130
ASSERTMSG(
"View index notify handle in directory notify list!", Notify->
FullDirectoryName !=
NULL);
01131
01132
01133
01134
01135
01136
01137
if (Notify->
FullDirectoryName->Length == 0) {
01138
01139
continue;
01140 }
01141
01142
01143
01144
01145
01146
if (!(FilterMatch & Notify->
CompletionFilter)) {
01147
01148
continue;
01149 }
01150
01151
01152
01153
01154
01155
01156
if (!ARGUMENT_PRESENT( NormalizedParentName )) {
01157 NormalizedParent.Buffer = FullTargetName->Buffer;
01158 NormalizedParent.Length = TargetNameOffset;
01159
01160
if (NormalizedParent.Length != Notify->
CharacterSize) {
01161
01162 NormalizedParent.Length -= Notify->
CharacterSize;
01163 }
01164
01165 NormalizedParent.MaximumLength = NormalizedParent.Length;
01166
01167 NormalizedParentName = &NormalizedParent;
01168 }
01169
01170
01171
01172
01173
01174
01175
01176
if (Notify->
FullDirectoryName->Length > NormalizedParentName->Length) {
01177
01178
continue;
01179 }
01180
01181
01182
01183
01184
01185
01186
if (NormalizedParentName->Length == Notify->
FullDirectoryName->Length) {
01187
01188 NotifyIsParent =
TRUE;
01189
01190
01191
01192
01193
01194 }
else if (!
FlagOn( Notify->
Flags,
NOTIFY_WATCH_TREE )) {
01195
01196
continue;
01197
01198
01199
01200
01201
01202
01203
01204
01205 }
else {
01206
01207
if (!
FlagOn( Notify->
Flags,
NOTIFY_DIR_IS_ROOT )) {
01208
01209
01210
01211
01212
01213
if (Notify->
CharacterSize ==
sizeof(
CHAR )) {
01214
01215
if (*(
Add2Ptr( NormalizedParentName->Buffer,
01216 Notify->
FullDirectoryName->Length,
01217 PCHAR )) !=
'\\') {
01218
01219
continue;
01220 }
01221
01222 }
else if (*(
Add2Ptr( NormalizedParentName->Buffer,
01223 Notify->
FullDirectoryName->Length,
01224 PWCHAR )) !=
L'\\') {
01225
01226
continue;
01227 }
01228 }
01229
01230 NotifyIsParent =
FALSE;
01231 }
01232
01233
01234
01235
01236
01237
01238
if (!RtlEqualMemory( Notify->
FullDirectoryName->Buffer,
01239 NormalizedParentName->Buffer,
01240 Notify->
FullDirectoryName->Length )) {
01241
01242
continue;
01243 }
01244
01245
01246
01247
01248
01249
01250
if (!NotifyIsParent &&
01251 Notify->
TraverseCallback !=
NULL &&
01252 !Notify->
TraverseCallback( Notify->
FsContext,
01253 TargetContext,
01254 Notify->
SubjectContext )) {
01255
01256
continue;
01257 }
01258 }
01259
01260
01261
01262
01263
01264
01265
if (!
FlagOn( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY )
01266 && Notify->
BufferLength != 0) {
01267
01268 ULONG AllocationLength;
01269
01270 AllocationLength = 0;
01271 NotifyIrp =
NULL;
01272
01273
01274
01275
01276
01277
01278
01279
if (Notify->
ThisBufferLength == 0) {
01280
01281
01282
01283
01284
01285
if (!IsListEmpty( &Notify->
NotifyIrps )) {
01286
01287
PIO_STACK_LOCATION IrpSp;
01288
01289 NotifyIrp = CONTAINING_RECORD( Notify->
NotifyIrps.Flink,
01290
IRP,
01291 Tail.Overlay.ListEntry );
01292
01293 IrpSp =
IoGetCurrentIrpStackLocation( NotifyIrp );
01294
01295 AllocationLength = IrpSp->
Parameters.NotifyDirectory.Length;
01296
01297
01298
01299
01300
01301 }
else {
01302
01303 AllocationLength = Notify->
BufferLength;
01304 }
01305
01306
01307
01308
01309
01310 }
else {
01311
01312 AllocationLength = Notify->
ThisBufferLength;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
if (!NotifyIsParent) {
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
if (!ViewIndex) {
01333
01334
01335
01336
01337
01338
01339
if (
FlagOn( Notify->
Flags,
NOTIFY_DIR_IS_ROOT ) ||
01340 NormalizedParentName->Buffer != FullTargetName->Buffer) {
01341
01342
01343
01344
01345
01346
01347
if (ParentName.Buffer ==
NULL) {
01348
01349 ParentName.Buffer = FullTargetName->Buffer;
01350 ParentName.Length = TargetNameOffset;
01351
01352
if (ParentName.Length != Notify->
CharacterSize) {
01353
01354 ParentName.Length -= Notify->
CharacterSize;
01355 }
01356
01357 ParentName.MaximumLength = ParentName.Length;
01358 }
01359
01360
01361
01362
01363
01364
01365
01366
01367 ComponentCount = 0;
01368 CurrentOffset = 0;
01369
01370
01371
01372
01373
01374
if (
FlagOn( Notify->
Flags,
NOTIFY_DIR_IS_ROOT )) {
01375
01376 NOTHING;
01377
01378 }
else {
01379
01380 ULONG ParentComponentCount;
01381 ULONG ParentOffset;
01382
01383 ParentComponentCount = 1;
01384 ParentOffset = 0;
01385
01386
if (Notify->
CharacterSize ==
sizeof(
CHAR )) {
01387
01388
01389
01390
01391
01392
01393
01394
while (ParentOffset < Notify->
FullDirectoryName->Length) {
01395
01396
if (*((PCHAR) Notify->
FullDirectoryName->Buffer + ParentOffset) ==
'\\') {
01397
01398 ParentComponentCount += 1;
01399 }
01400
01401 ParentOffset += 1;
01402 }
01403
01404
while (
TRUE) {
01405
01406
if (*((PCHAR) ParentName.Buffer + CurrentOffset) ==
'\\') {
01407
01408 ComponentCount += 1;
01409
01410
if (ComponentCount == ParentComponentCount) {
01411
01412
break;
01413 }
01414
01415 }
01416
01417 CurrentOffset += 1;
01418 }
01419
01420 }
else {
01421
01422
01423
01424
01425
01426
01427
01428
while (ParentOffset < Notify->
FullDirectoryName->Length /
sizeof( WCHAR )) {
01429
01430
if (*((PWCHAR) Notify->
FullDirectoryName->Buffer + ParentOffset) ==
'\\') {
01431
01432 ParentComponentCount += 1;
01433 }
01434
01435 ParentOffset += 1;
01436 }
01437
01438
while (
TRUE) {
01439
01440
if (*((PWCHAR) ParentName.Buffer + CurrentOffset) ==
L'\\') {
01441
01442 ComponentCount += 1;
01443
01444
if (ComponentCount == ParentComponentCount) {
01445
01446
break;
01447 }
01448 }
01449
01450 CurrentOffset += 1;
01451 }
01452
01453
01454
01455
01456
01457 CurrentOffset *= Notify->
CharacterSize;
01458 }
01459 }
01460
01461
01462
01463
01464
01465
01466
01467 CurrentOffset += Notify->
CharacterSize;
01468
01469 TargetParent.Buffer =
Add2Ptr( ParentName.Buffer,
01470 CurrentOffset,
01471 PCHAR );
01472 TargetParent.MaximumLength =
01473 TargetParent.Length = ParentName.Length - (
USHORT) CurrentOffset;
01474
01475
01476
01477
01478
01479
01480 }
else {
01481
01482 TargetParent.Buffer =
Add2Ptr( NormalizedParentName->Buffer,
01483 (Notify->
FullDirectoryName->Length +
01484 Notify->
CharacterSize),
01485 PCHAR );
01486
01487 TargetParent.MaximumLength =
01488 TargetParent.Length = NormalizedParentName->Length -
01489 Notify->
FullDirectoryName->Length -
01490 Notify->
CharacterSize;
01491
01492 }
01493 }
01494
01495 }
else {
01496
01497
01498
01499
01500
01501 TargetParent.Length = 0;
01502 }
01503
01504
01505
01506
01507
01508 SizeOfEntry = FIELD_OFFSET( FILE_NOTIFY_INFORMATION,
FileName );
01509
01510
if (ViewIndex) {
01511
01512
01513
01514
01515
01516
01517
01518
ASSERT(ARGUMENT_PRESENT( StreamName ));
01519
01520 SizeOfEntry += StreamName->Length;
01521
01522 }
else {
01523
01524
01525
01526
01527
01528
01529
if (!NotifyIsParent) {
01530
01531
if (Notify->
CharacterSize ==
sizeof(
CHAR )) {
01532
01533 SizeOfEntry += RtlOemStringToCountedUnicodeSize( &TargetParent );
01534
01535 }
else {
01536
01537 SizeOfEntry += TargetParent.Length;
01538 }
01539
01540
01541
01542
01543
01544 SizeOfEntry +=
sizeof( WCHAR );
01545 }
01546
01547
01548
01549
01550
01551
if (TargetName.Buffer ==
NULL) {
01552
01553 TargetName.Buffer =
Add2Ptr( FullTargetName->Buffer, TargetNameOffset, PCHAR );
01554 TargetName.MaximumLength =
01555 TargetName.Length = FullTargetName->Length - TargetNameOffset;
01556 }
01557
01558
if (Notify->
CharacterSize ==
sizeof(
CHAR )) {
01559
01560 SizeOfEntry += RtlOemStringToCountedUnicodeSize( &TargetName );
01561
01562 }
else {
01563
01564 SizeOfEntry += TargetName.Length;
01565 }
01566
01567
01568
01569
01570
01571
01572
if (ARGUMENT_PRESENT( StreamName )) {
01573
01574
01575
01576
01577
01578
if (Notify->
CharacterSize ==
sizeof( WCHAR )) {
01579
01580 SizeOfEntry += (StreamName->Length +
sizeof( WCHAR ));
01581
01582 }
else {
01583
01584 SizeOfEntry += (RtlOemStringToCountedUnicodeSize( StreamName )
01585 +
sizeof(
CHAR ));
01586 }
01587 }
01588 }
01589
01590
01591
01592
01593
01594 NextEntryOffset = (ULONG)
LongAlign( Notify->
DataLength );
01595
01596
if (SizeOfEntry <= AllocationLength
01597 && (NextEntryOffset + SizeOfEntry) <= AllocationLength) {
01598
01599 PFILE_NOTIFY_INFORMATION NotifyInfo =
NULL;
01600
01601
01602
01603
01604
01605
01606
if (Notify->
Buffer !=
NULL) {
01607
01608 NotifyInfo =
Add2Ptr( Notify->
Buffer,
01609 Notify->
LastEntry,
01610 PFILE_NOTIFY_INFORMATION );
01611
01612 NotifyInfo->NextEntryOffset = NextEntryOffset - Notify->
LastEntry;
01613
01614 Notify->
LastEntry = NextEntryOffset;
01615
01616 NotifyInfo =
Add2Ptr( Notify->
Buffer,
01617 Notify->
LastEntry,
01618 PFILE_NOTIFY_INFORMATION );
01619
01620
01621
01622
01623
01624
01625 }
else if (NotifyIrp !=
NULL) {
01626
01627
if (NotifyIrp->
AssociatedIrp.SystemBuffer !=
NULL) {
01628
01629 Notify->
Buffer =
01630 NotifyInfo = NotifyIrp->
AssociatedIrp.SystemBuffer;
01631
01632 Notify->
ThisBufferLength = AllocationLength;
01633
01634 }
else if (NotifyIrp->
MdlAddress !=
NULL) {
01635
01636 Notify->
Buffer =
01637 NotifyInfo =
MmGetSystemAddressForMdl( NotifyIrp->
MdlAddress );
01638
01639 Notify->
ThisBufferLength = AllocationLength;
01640 }
01641 }
01642
01643
01644
01645
01646
01647
01648
if (Notify->
Buffer ==
NULL) {
01649
01650 BOOLEAN ChargedQuota =
FALSE;
01651
01652
try {
01653
01654
PsChargePoolQuota( Notify->
OwningProcess,
01655
PagedPool,
01656 AllocationLength );
01657
01658 ChargedQuota =
TRUE;
01659
01660 Notify->
AllocatedBuffer =
01661 Notify->
Buffer =
FsRtlpAllocatePool(
PagedPool,
01662 AllocationLength );
01663
01664 Notify->
ThisBufferLength = AllocationLength;
01665
01666 NotifyInfo = Notify->
Buffer;
01667
01668 } except(( ExceptionCode = GetExceptionCode(),
FsRtlIsNtstatusExpected(ExceptionCode))
01669 ?
EXCEPTION_EXECUTE_HANDLER
01670 :
EXCEPTION_CONTINUE_SEARCH ) {
01671
01672
01673
ASSERT( (ExceptionCode == STATUS_INSUFFICIENT_RESOURCES) ||
01674 (ExceptionCode == STATUS_QUOTA_EXCEEDED) );
01675
01676
01677
01678
01679
01680
if (ChargedQuota) {
01681
01682
PsReturnPoolQuota( Notify->
OwningProcess,
01683
PagedPool,
01684 AllocationLength );
01685
01686 }
01687
01688
01689
01690
01691
01692
01693
SetFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
01694 }
01695 }
01696
01697
01698
01699
01700
01701
01702
01703
if (NotifyInfo !=
NULL) {
01704
01705
01706
01707
01708
01709
if (
FsRtlNotifyUpdateBuffer( NotifyInfo,
01710
Action,
01711 &TargetParent,
01712 &TargetName,
01713 StreamName,
01714 (BOOLEAN) (Notify->
CharacterSize ==
sizeof( WCHAR )),
01715 SizeOfEntry )) {
01716
01717
01718
01719
01720
01721 Notify->
DataLength = NextEntryOffset + SizeOfEntry;
01722
01723
01724
01725
01726
01727
01728 }
else {
01729
01730
SetFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
01731 }
01732 }
01733
01734 }
else {
01735
01736
SetFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
01737 }
01738
01739
01740
01741
01742
01743
01744
01745
if (
FlagOn( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY )
01746 && Notify->
Buffer !=
NULL) {
01747
01748
if (Notify->
AllocatedBuffer !=
NULL) {
01749
01750
PsReturnPoolQuota( Notify->
OwningProcess,
01751
PagedPool,
01752 Notify->
ThisBufferLength );
01753
01754
ExFreePool( Notify->
AllocatedBuffer );
01755 }
01756
01757 Notify->
AllocatedBuffer = Notify->
Buffer =
NULL;
01758
01759 Notify->
ThisBufferLength = Notify->
DataLength = Notify->
LastEntry = 0;
01760 }
01761 }
01762
01763
01764
01765
01766
01767
01768
if (
Action == FILE_ACTION_RENAMED_OLD_NAME) {
01769
01770
SetFlag( Notify->
Flags,
NOTIFY_DEFER_NOTIFY );
01771
01772 }
else {
01773
01774
ClearFlag( Notify->
Flags,
NOTIFY_DEFER_NOTIFY );
01775
01776
if (!IsListEmpty( &Notify->
NotifyIrps )) {
01777
01778
FsRtlNotifyCompleteIrpList( Notify, STATUS_SUCCESS );
01779 }
01780 }
01781 }
01782
01783 } finally {
01784
01785
ReleaseNotifySync( NotifySync );
01786
01787
DebugTrace( -1,
Dbg,
"FsRtlNotifyFullReportChange: Exit\n", 0 );
01788 }
01789
01790
return;
01791 }
01792
01793
01794
VOID
01795 FsRtlNotifyCleanup (
01796 IN PNOTIFY_SYNC NotifySync,
01797 IN PLIST_ENTRY NotifyList,
01798 IN PVOID FsContext
01799 )
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828 {
01829
PNOTIFY_CHANGE Notify;
01830
PSECURITY_SUBJECT_CONTEXT SubjectContext =
NULL;
01831
01832
PAGED_CODE();
01833
01834
DebugTrace( +1,
Dbg,
"FsRtlNotifyCleanup: Entered\n", 0 );
01835
DebugTrace( 0,
Dbg,
"Mutex -> %08lx\n", Mutex );
01836
DebugTrace( 0,
Dbg,
"Notify List -> %08lx\n", NotifyList );
01837
DebugTrace( 0,
Dbg,
"FsContext -> %08lx\n", FsContext );
01838
01839
01840
01841
01842
01843
AcquireNotifySync( NotifySync );
01844
01845
01846
01847
01848
01849
try {
01850
01851
01852
01853
01854
01855 Notify =
FsRtlIsNotifyOnList( NotifyList, FsContext );
01856
01857
01858
01859
01860
01861
if (Notify !=
NULL) {
01862
01863
01864
01865
01866
01867
SetFlag( Notify->
Flags,
NOTIFY_CLEANUP_CALLED );
01868
01869
if (!IsListEmpty( &Notify->
NotifyIrps )) {
01870
01871
FsRtlNotifyCompleteIrpList( Notify, STATUS_NOTIFY_CLEANUP );
01872 }
01873
01874 RemoveEntryList( &Notify->
NotifyList );
01875
01876 InterlockedDecrement( &Notify->
ReferenceCount );
01877
01878
if (Notify->
ReferenceCount == 0) {
01879
01880
if (Notify->
AllocatedBuffer !=
NULL) {
01881
01882
PsReturnPoolQuota( Notify->
OwningProcess,
01883
PagedPool,
01884 Notify->
ThisBufferLength );
01885
01886
ExFreePool( Notify->
AllocatedBuffer );
01887 }
01888
01889
if (Notify->
FullDirectoryName !=
NULL) {
01890
01891 SubjectContext = Notify->
SubjectContext;
01892 }
01893
01894
ExFreePool( Notify );
01895 }
01896 }
01897
01898 } finally {
01899
01900
ReleaseNotifySync( NotifySync );
01901
01902
if (SubjectContext !=
NULL) {
01903
01904
SeReleaseSubjectContext( SubjectContext );
01905
ExFreePool( SubjectContext );
01906 }
01907
01908
DebugTrace( -1,
Dbg,
"FsRtlNotifyCleanup: Exit\n", 0 );
01909 }
01910
01911
return;
01912 }
01913
01914
01915
01916
01917
01918
01919
PNOTIFY_CHANGE
01920 FsRtlIsNotifyOnList (
01921 IN PLIST_ENTRY NotifyListHead,
01922 IN PVOID FsContext
01923 )
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946 {
01947 PLIST_ENTRY Link;
01948
01949
PNOTIFY_CHANGE ThisNotify;
01950
PNOTIFY_CHANGE Notify;
01951
01952
PAGED_CODE();
01953
01954
DebugTrace( +1,
Dbg,
"FsRtlIsNotifyOnList: Entered\n", 0 );
01955
01956
01957
01958
01959
01960 Notify =
NULL;
01961
01962
01963
01964
01965
01966
for (Link = NotifyListHead->Flink;
01967 Link != NotifyListHead;
01968 Link = Link->Flink) {
01969
01970
01971
01972
01973
01974 ThisNotify = CONTAINING_RECORD( Link,
NOTIFY_CHANGE, NotifyList );
01975
01976
01977
01978
01979
01980
01981
if (ThisNotify->
FsContext == FsContext) {
01982
01983 Notify = ThisNotify;
01984
break;
01985 }
01986 }
01987
01988
DebugTrace( 0,
Dbg,
"Notify Structure -> %08lx\n", Notify );
01989
DebugTrace( -1,
Dbg,
"FsRtlIsNotifyOnList: Exit\n", 0 );
01990
01991
return Notify;
01992 }
01993
01994
01995
01996
01997
01998
01999
VOID
02000 FsRtlNotifyCompleteIrp (
02001 IN
PIRP NotifyIrp,
02002 IN PNOTIFY_CHANGE Notify,
02003 IN ULONG DataLength,
02004 IN NTSTATUS Status,
02005 IN ULONG CheckCancel
02006 )
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036 {
02037
PIO_STACK_LOCATION IrpSp;
02038
02039
PAGED_CODE();
02040
02041
DebugTrace( +1,
Dbg,
"FsRtlIsNotifyCompleteIrp: Entered\n", 0 );
02042
02043
02044
02045
02046
02047
02048
02049
if (
FsRtlNotifySetCancelRoutine( NotifyIrp, Notify ) || !CheckCancel) {
02050
02051
02052
02053
02054
02055
if (
Status == STATUS_SUCCESS) {
02056
02057
02058
02059
02060
02061 IrpSp =
IoGetCurrentIrpStackLocation( NotifyIrp );
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
if (DataLength == 0
02072 || IrpSp->
Parameters.NotifyDirectory.Length < DataLength) {
02073
02074
Status = STATUS_NOTIFY_ENUM_DIR;
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097 }
else {
02098
02099
if (Notify->AllocatedBuffer !=
NULL) {
02100
02101
02102
02103
02104
02105
02106
try {
02107
02108
if (NotifyIrp->AssociatedIrp.SystemBuffer !=
NULL) {
02109
02110 RtlCopyMemory( NotifyIrp->AssociatedIrp.SystemBuffer,
02111 Notify->AllocatedBuffer,
02112 DataLength );
02113
02114 }
else if (NotifyIrp->MdlAddress !=
NULL) {
02115
02116 RtlCopyMemory(
MmGetSystemAddressForMdl( NotifyIrp->MdlAddress ),
02117 Notify->AllocatedBuffer,
02118 DataLength );
02119
02120 }
else if (!
FlagOn( IrpSp->
Control,
SL_PENDING_RETURNED )) {
02121
02122 RtlCopyMemory( NotifyIrp->UserBuffer,
02123 Notify->AllocatedBuffer,
02124 DataLength );
02125
02126 }
else {
02127
02128 NotifyIrp->Flags |= (
IRP_BUFFERED_IO |
IRP_INPUT_OPERATION |
IRP_DEALLOCATE_BUFFER);
02129 NotifyIrp->AssociatedIrp.SystemBuffer = Notify->AllocatedBuffer;
02130
02131 }
02132
02133 } except(
EXCEPTION_EXECUTE_HANDLER ) {
02134
02135
Status = STATUS_NOTIFY_ENUM_DIR;
02136 DataLength = 0;
02137 }
02138
02139
02140
02141
02142
02143
02144
PsReturnPoolQuota( Notify->OwningProcess,
PagedPool, Notify->ThisBufferLength );
02145
02146
if (Notify->AllocatedBuffer != NotifyIrp->AssociatedIrp.SystemBuffer
02147 && Notify->AllocatedBuffer !=
NULL) {
02148
02149
ExFreePool( Notify->AllocatedBuffer );
02150 }
02151
02152 Notify->AllocatedBuffer =
NULL;
02153 Notify->ThisBufferLength = 0;
02154 }
02155
02156
02157
02158
02159
02160 NotifyIrp->IoStatus.Information = DataLength;
02161
02162
02163
02164
02165
02166
02167 Notify->Buffer =
NULL;
02168 }
02169 }
02170
02171
02172
02173
02174
02175
IoMarkIrpPending( NotifyIrp );
02176
02177
02178
02179
02180
02181
FsRtlCompleteRequest( NotifyIrp,
Status );
02182 }
02183
02184
DebugTrace( -1,
Dbg,
"FsRtlIsNotifyCompleteIrp: Exit\n", 0 );
02185
02186
return;
02187 }
02188
02189
02190
02191
02192
02193
02194 BOOLEAN
02195 FsRtlNotifySetCancelRoutine (
02196 IN
PIRP NotifyIrp,
02197 IN PNOTIFY_CHANGE Notify OPTIONAL
02198 )
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222 {
02223 BOOLEAN ClearedCancel =
FALSE;
02224
PDRIVER_CANCEL CurrentCancel;
02225
02226
02227
02228
02229
02230
IoAcquireCancelSpinLock( &NotifyIrp->CancelIrql );
02231
02232
02233
02234
02235
02236
02237
if (ARGUMENT_PRESENT( Notify )) {
02238
02239 CurrentCancel =
IoSetCancelRoutine( NotifyIrp,
NULL );
02240 NotifyIrp->IoStatus.Information = 0;
02241
02242
IoReleaseCancelSpinLock( NotifyIrp->CancelIrql );
02243
02244
02245
02246
02247
02248
02249
if (CurrentCancel !=
NULL) {
02250
02251 InterlockedDecrement( &Notify->ReferenceCount );
02252 ClearedCancel =
TRUE;
02253 }
02254
02255
02256
02257
02258
02259
02260 }
else if (NotifyIrp->Cancel) {
02261
02262
DebugTrace( 0,
Dbg,
"Irp has been cancelled\n", 0 );
02263
02264
FsRtlCancelNotify(
NULL, NotifyIrp );
02265
02266 }
else {
02267
02268
02269
02270
02271
02272
IoSetCancelRoutine( NotifyIrp,
FsRtlCancelNotify );
02273
02274
IoReleaseCancelSpinLock( NotifyIrp->CancelIrql );
02275 }
02276
02277
return ClearedCancel;
02278 }
02279
02280
02281
02282
02283
02284
02285 BOOLEAN
02286 FsRtlNotifyUpdateBuffer (
02287 IN PFILE_NOTIFY_INFORMATION NotifyInfo,
02288 IN ULONG FileAction,
02289 IN PSTRING ParentName,
02290 IN PSTRING TargetName,
02291 IN PSTRING StreamName OPTIONAL,
02292 IN BOOLEAN UnicodeName,
02293 IN ULONG SizeOfEntry
02294 )
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327 {
02328 BOOLEAN CopiedToBuffer;
02329 ULONG BufferOffset = 0;
02330
02331
PAGED_CODE();
02332
02333
DebugTrace( +1,
Dbg,
"FsRtlNotifyUpdateBuffer: Entered\n", 0 );
02334
02335
02336
02337
02338
02339
02340
02341
try {
02342
02343
02344
02345
02346
02347 NotifyInfo->NextEntryOffset = 0;
02348 NotifyInfo->Action = FileAction;
02349
02350 NotifyInfo->FileNameLength = SizeOfEntry - FIELD_OFFSET( FILE_NOTIFY_INFORMATION,
FileName );
02351
02352
02353
02354
02355
02356
if (UnicodeName) {
02357
02358
if (ParentName->Length != 0) {
02359
02360 RtlCopyMemory( NotifyInfo->FileName,
02361 ParentName->Buffer,
02362 ParentName->Length );
02363
02364 *(
Add2Ptr( NotifyInfo->FileName, ParentName->Length, PWCHAR )) =
L'\\';
02365 BufferOffset = ParentName->Length +
sizeof( WCHAR );
02366 }
02367
02368 RtlCopyMemory(
Add2Ptr( NotifyInfo->FileName,
02369 BufferOffset,
02370 PVOID ),
02371 TargetName->Buffer,
02372 TargetName->Length );
02373
02374
if (ARGUMENT_PRESENT( StreamName )) {
02375
02376 BufferOffset += TargetName->Length;
02377
02378 *(
Add2Ptr( NotifyInfo->FileName, BufferOffset, PWCHAR )) =
L':';
02379
02380 RtlCopyMemory(
Add2Ptr( NotifyInfo->FileName,
02381 BufferOffset +
sizeof( WCHAR ),
02382 PVOID ),
02383 StreamName->Buffer,
02384 StreamName->Length );
02385 }
02386
02387
02388
02389
02390
02391 }
else {
02392
02393 ULONG BufferLength;
02394
02395
if (ParentName->Length != 0) {
02396
02397
RtlOemToUnicodeN( NotifyInfo->FileName,
02398 NotifyInfo->FileNameLength,
02399 &BufferLength,
02400 ParentName->Buffer,
02401 ParentName->Length );
02402
02403 *(
Add2Ptr( NotifyInfo->FileName, BufferLength, PWCHAR )) =
L'\\';
02404
02405 BufferOffset = BufferLength +
sizeof( WCHAR );
02406 }
02407
02408
02409
02410
02411
02412
if (ParentName->Length == 0) {
02413
02414
ASSERT(ARGUMENT_PRESENT( StreamName ));
02415
02416 RtlCopyMemory(
Add2Ptr( NotifyInfo->FileName,
02417 BufferOffset,
02418 PCHAR ),
02419 StreamName->Buffer,
02420 StreamName->Length );
02421
02422 }
else {
02423
02424
RtlOemToUnicodeN(
Add2Ptr( NotifyInfo->FileName,
02425 BufferOffset,
02426 PWCHAR ),
02427 NotifyInfo->FileNameLength,
02428 &BufferLength,
02429 TargetName->Buffer,
02430 TargetName->Length );
02431
02432
if (ARGUMENT_PRESENT( StreamName )) {
02433
02434 BufferOffset += BufferLength;
02435
02436 *(
Add2Ptr( NotifyInfo->FileName, BufferOffset, PWCHAR )) =
L':';
02437
02438
RtlOemToUnicodeN(
Add2Ptr( NotifyInfo->FileName,
02439 BufferOffset +
sizeof( WCHAR ),
02440 PWCHAR ),
02441 NotifyInfo->FileNameLength,
02442 &BufferLength,
02443 StreamName->Buffer,
02444 StreamName->Length );
02445 }
02446 }
02447 }
02448
02449 CopiedToBuffer =
TRUE;
02450
02451 } except(
EXCEPTION_EXECUTE_HANDLER ) {
02452
02453 CopiedToBuffer =
FALSE;
02454 }
02455
02456
DebugTrace( -1,
Dbg,
"FsRtlNotifyUpdateBuffer: Exit\n", 0 );
02457
02458
return CopiedToBuffer;
02459 }
02460
02461
02462
02463
02464
02465
02466
VOID
02467 FsRtlNotifyCompleteIrpList (
02468 IN OUT PNOTIFY_CHANGE Notify,
02469 IN NTSTATUS Status
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
PIRP Irp;
02498 ULONG DataLength;
02499
02500
DebugTrace( +1,
Dbg,
"FsRtlNotifyCompleteIrpList: Entered\n", 0 );
02501
02502 DataLength = Notify->DataLength;
02503
02504
02505
02506
02507
02508
ClearFlag( Notify->Flags,
NOTIFY_IMMEDIATE_NOTIFY );
02509 Notify->DataLength = 0;
02510 Notify->LastEntry = 0;
02511
02512
02513
02514
02515
02516
02517
do {
02518
02519
Irp = CONTAINING_RECORD( Notify->NotifyIrps.Flink,
IRP, Tail.Overlay.ListEntry );
02520
02521 RemoveHeadList( &Notify->NotifyIrps );
02522
02523
02524
02525
02526
02527
FsRtlNotifyCompleteIrp(
Irp,
02528 Notify,
02529 DataLength,
02530
Status,
02531
TRUE );
02532
02533
02534
02535
02536
02537
if (
Status == STATUS_SUCCESS) {
02538
02539
break;
02540 }
02541
02542 }
while (!IsListEmpty( &Notify->NotifyIrps ));
02543
02544
DebugTrace( -1,
Dbg,
"FsRtlNotifyCompleteIrpList: Exit\n", 0 );
02545
02546
return;
02547 }
02548
02549
02550
02551
02552
02553
02554
VOID
02555 FsRtlCancelNotify (
02556 IN
PDEVICE_OBJECT DeviceObject,
02557 IN
PIRP ThisIrp
02558 )
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582 {
02583
PSECURITY_SUBJECT_CONTEXT SubjectContext =
NULL;
02584
02585
PNOTIFY_CHANGE Notify;
02586
PNOTIFY_SYNC NotifySync;
02587 LONG ExceptionCode;
02588
02589 UNREFERENCED_PARAMETER( DeviceObject );
02590
02591
DebugTrace( +1,
Dbg,
"FsRtlCancelNotify: Entered\n", 0 );
02592
DebugTrace( 0,
Dbg,
"Irp -> %08lx\n",
Irp );
02593
02594
02595
02596
02597
02598 Notify = (
PNOTIFY_CHANGE) ThisIrp->IoStatus.Information;
02599
02600
02601
02602
02603
02604
IoSetCancelRoutine( ThisIrp,
NULL );
02605 ThisIrp->IoStatus.Information = 0;
02606
IoReleaseCancelSpinLock( ThisIrp->CancelIrql );
02607
02608
FsRtlEnterFileSystem();
02609
02610
02611
02612
02613
02614 NotifySync = Notify->
NotifySync;
02615
AcquireNotifySync( NotifySync );
02616
02617
02618
02619
02620
02621
try {
02622
02623
02624
02625
02626
02627 RemoveEntryList( &ThisIrp->Tail.Overlay.ListEntry );
02628
02629
IoMarkIrpPending( ThisIrp );
02630
02631
02632
02633
02634
02635
02636
if (Notify->
Buffer !=
NULL
02637 && Notify->
AllocatedBuffer ==
NULL
02638
02639 && ((ThisIrp->MdlAddress !=
NULL
02640 &&
MmGetSystemAddressForMdl( ThisIrp->MdlAddress ) == Notify->
Buffer)
02641
02642 || (Notify->
Buffer == ThisIrp->AssociatedIrp.SystemBuffer))) {
02643
02644
PIRP NextIrp;
02645 PVOID NewBuffer;
02646 ULONG NewBufferLength;
02647
PIO_STACK_LOCATION IrpSp;
02648
02649
02650
02651
02652
02653 NewBuffer =
NULL;
02654 NewBufferLength = 0;
02655
02656
02657
02658
02659
02660
02661
02662
if (!IsListEmpty( &Notify->
NotifyIrps )) {
02663
02664 NextIrp = CONTAINING_RECORD( Notify->
NotifyIrps.Flink,
02665
IRP,
02666 Tail.Overlay.ListEntry );
02667
02668 IrpSp =
IoGetCurrentIrpStackLocation( NextIrp );
02669
02670
02671
02672
02673
02674
02675
if (IrpSp->
Parameters.NotifyDirectory.Length >= Notify->
DataLength) {
02676
02677
02678
02679
02680
02681
02682
if (NextIrp->
AssociatedIrp.SystemBuffer !=
NULL) {
02683
02684 NewBuffer = NextIrp->
AssociatedIrp.SystemBuffer;
02685
02686 }
else if (NextIrp->
MdlAddress !=
NULL) {
02687
02688 NewBuffer =
MmGetSystemAddressForMdl( NextIrp->
MdlAddress );
02689 }
02690
02691 NewBufferLength = IrpSp->
Parameters.NotifyDirectory.Length;
02692
02693
if (NewBufferLength > Notify->
BufferLength) {
02694
02695 NewBufferLength = Notify->
BufferLength;
02696 }
02697 }
02698
02699
02700
02701
02702
02703
02704 }
else if (Notify->
BufferLength >= Notify->
DataLength) {
02705
02706 NewBufferLength = Notify->
BufferLength;
02707 }
02708
02709
02710
02711
02712
02713
02714
02715
02716
if (NewBufferLength != 0) {
02717
02718 BOOLEAN ChargedQuota;
02719
02720
try {
02721
02722 ChargedQuota =
FALSE;
02723
02724
if (NewBuffer ==
NULL) {
02725
02726
PsChargePoolQuota( Notify->
OwningProcess,
02727
PagedPool,
02728 NewBufferLength );
02729
02730 ChargedQuota =
TRUE;
02731
02732
02733
02734
02735
02736
02737
02738 NewBuffer =
FsRtlpAllocatePool(
PagedPool,
02739 NewBufferLength );
02740
02741 Notify->
AllocatedBuffer = NewBuffer;
02742 }
02743
02744
02745
02746
02747
02748 RtlCopyMemory( NewBuffer,
02749 Notify->
Buffer,
02750 Notify->
DataLength );
02751
02752
02753
02754
02755
02756 Notify->
ThisBufferLength = NewBufferLength;
02757 Notify->
Buffer = NewBuffer;
02758
02759 } except(
FsRtlIsNtstatusExpected( ExceptionCode = GetExceptionCode()) ?
02760
EXCEPTION_EXECUTE_HANDLER :
02761
EXCEPTION_CONTINUE_SEARCH ) {
02762
02763
ASSERT( (ExceptionCode == STATUS_INSUFFICIENT_RESOURCES) ||
02764 (ExceptionCode == STATUS_QUOTA_EXCEEDED) );
02765
02766
02767
02768
02769
02770
if (ChargedQuota) {
02771
02772
PsReturnPoolQuota( Notify->
OwningProcess,
02773
PagedPool,
02774 NewBufferLength );
02775 }
02776
02777
02778
02779
02780
02781
02782
SetFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
02783 }
02784
02785
02786
02787
02788
02789 }
else {
02790
02791
SetFlag( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY );
02792 }
02793
02794
02795
02796
02797
02798
02799
if (
FlagOn( Notify->
Flags,
NOTIFY_IMMEDIATE_NOTIFY )) {
02800
02801
02802
02803
02804
02805
02806 Notify->
AllocatedBuffer = Notify->
Buffer =
NULL;
02807
02808 Notify->
ThisBufferLength =
02809 Notify->
DataLength = Notify->
LastEntry = 0;
02810 }
02811 }
02812
02813
02814
02815
02816
02817
FsRtlCompleteRequest( ThisIrp, STATUS_CANCELLED );
02818
02819
02820
02821
02822
02823 InterlockedDecrement( &Notify->
ReferenceCount );
02824
02825
if (Notify->
ReferenceCount == 0) {
02826
02827
if (Notify->
AllocatedBuffer !=
NULL) {
02828
02829
PsReturnPoolQuota( Notify->
OwningProcess,
02830
PagedPool,
02831 Notify->
ThisBufferLength );
02832
02833
ExFreePool( Notify->
AllocatedBuffer );
02834 }
02835
02836
if (Notify->
FullDirectoryName !=
NULL) {
02837
02838 SubjectContext = Notify->
SubjectContext;
02839 }
02840
02841
ExFreePool( Notify );
02842 Notify =
NULL;
02843 }
02844
02845 } finally {
02846
02847
02848
02849
02850
02851
ReleaseNotifySync( NotifySync );
02852
02853
if (SubjectContext !=
NULL) {
02854
02855
SeReleaseSubjectContext( SubjectContext );
02856
ExFreePool( SubjectContext );
02857 }
02858
02859
FsRtlExitFileSystem();
02860
02861
DebugTrace( -1,
Dbg,
"FsRtlCancelNotify: Exit\n", 0 );
02862 }
02863
02864
return;
02865 }
02866
02867
02868
02869
02870
02871
02872
VOID
02873 FsRtlCheckNotifyForDelete (
02874 IN PLIST_ENTRY NotifyListHead,
02875 IN PVOID StreamID
02876 )
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898 {
02899 PLIST_ENTRY Link;
02900
02901
PNOTIFY_CHANGE ThisNotify;
02902
02903
PAGED_CODE();
02904
02905
02906
02907
02908
02909
for (Link = NotifyListHead->Flink;
02910 Link != NotifyListHead;
02911 Link = Link->Flink) {
02912
02913
02914
02915
02916
02917 ThisNotify = CONTAINING_RECORD( Link,
NOTIFY_CHANGE, NotifyList );
02918
02919
02920
02921
02922
02923
if (ThisNotify->
StreamID == StreamID) {
02924
02925
02926
02927
02928
02929
SetFlag( ThisNotify->
Flags,
NOTIFY_STREAM_IS_DELETED );
02930
02931
02932
02933
02934
02935
if (!IsListEmpty( &ThisNotify->
NotifyIrps )) {
02936
02937
FsRtlNotifyCompleteIrpList( ThisNotify, STATUS_DELETE_PENDING );
02938 }
02939 }
02940 }
02941
02942
return;
02943 }