ReactOS  0.4.14-dev-608-gd495a4f
notify.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for notify.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define FsRtlNotifyGetLastPartOffset(FullLen, TargLen, Type, Chr)
 

Functions

FORCEINLINE VOID FsRtlNotifyAcquireFastMutex (IN PREAL_NOTIFY_SYNC RealNotifySync)
 
FORCEINLINE VOID FsRtlNotifyReleaseFastMutex (IN PREAL_NOTIFY_SYNC RealNotifySync)
 
VOID FsRtlNotifyCompleteIrpList (IN PNOTIFY_CHANGE NotifyChange, IN NTSTATUS Status)
 
BOOLEAN FsRtlNotifySetCancelRoutine (IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
 
VOID NTAPI FsRtlCancelNotify (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
VOID FsRtlCheckNotifyForDelete (IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
 
PNOTIFY_CHANGE FsRtlIsNotifyOnList (IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
 
VOID FsRtlNotifyCompleteIrp (IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange, IN ULONG DataLength, IN NTSTATUS Status, IN BOOLEAN SkipCompletion)
 
BOOLEAN FsRtlNotifyUpdateBuffer (OUT PFILE_NOTIFY_INFORMATION OutputBuffer, IN ULONG Action, IN PSTRING ParentName, IN PSTRING TargetName, IN PSTRING StreamName, IN BOOLEAN IsUnicode, IN ULONG DataLength)
 
VOID NTAPI FsRtlNotifyChangeDirectory (IN PNOTIFY_SYNC NotifySync, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN PLIST_ENTRY NotifyList, IN BOOLEAN WatchTree, IN ULONG CompletionFilter, IN PIRP NotifyIrp)
 
VOID NTAPI FsRtlNotifyCleanup (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
 
VOID NTAPI FsRtlNotifyFilterChangeDirectory (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL, IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL)
 
VOID NTAPI FsRtlNotifyFilterReportChange (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
 
VOID NTAPI FsRtlNotifyFullChangeDirectory (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
 
VOID NTAPI FsRtlNotifyFullReportChange (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext)
 
VOID NTAPI FsRtlNotifyInitializeSync (IN PNOTIFY_SYNC *NotifySync)
 
VOID NTAPI FsRtlNotifyReportChange (IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN PUSHORT FileNamePartLength, IN ULONG FilterMatch)
 
VOID NTAPI FsRtlNotifyUninitializeSync (IN PNOTIFY_SYNC *NotifySync)
 

Macro Definition Documentation

◆ FsRtlNotifyGetLastPartOffset

#define FsRtlNotifyGetLastPartOffset (   FullLen,
  TargLen,
  Type,
  Chr 
)
Value:
for (FullPosition = 0; FullPosition < FullLen; ++FullPosition) \
if (((Type)NotifyChange->FullDirectoryName->Buffer)[FullPosition] == Chr) \
++FullNumberOfParts; \
for (LastPartOffset = 0; LastPartOffset < TargLen; ++LastPartOffset) { \
if ( ((Type)TargetDirectory.Buffer)[LastPartOffset] == Chr) { \
++TargetNumberOfParts; \
if (TargetNumberOfParts == FullNumberOfParts) \
break; \
} \
}
Type
Definition: Type.h:6

Definition at line 52 of file notify.c.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file notify.c.

Function Documentation

◆ FsRtlCancelNotify()

VOID NTAPI FsRtlCancelNotify ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 79 of file notify.c.

81 {
82  PVOID Buffer;
85  PIO_STACK_LOCATION Stack;
86  PNOTIFY_CHANGE NotifyChange;
87  PREAL_NOTIFY_SYNC RealNotifySync;
89 
90  /* Get the NOTIFY_CHANGE struct and reset it */
91  NotifyChange = (PNOTIFY_CHANGE)Irp->IoStatus.Information;
92  Irp->IoStatus.Information = 0;
93  /* Reset the cancel routine */
95  /* And release lock */
96  IoReleaseCancelSpinLock(Irp->CancelIrql);
97  /* Get REAL_NOTIFY_SYNC struct */
98  RealNotifySync = NotifyChange->NotifySync;
99 
100  FsRtlNotifyAcquireFastMutex(RealNotifySync);
101 
102  _SEH2_TRY
103  {
104  /* Remove the IRP from the notifications list and mark it pending */
105  RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
107 
108  /* Now, the tricky part - let's find a buffer big enough to hold the return data */
109  if (NotifyChange->Buffer && NotifyChange->AllocatedBuffer == NULL &&
110  ((Irp->MdlAddress && MmGetSystemAddressForMdl(Irp->MdlAddress) == NotifyChange->Buffer) ||
111  NotifyChange->Buffer == Irp->AssociatedIrp.SystemBuffer))
112  {
113  /* Assume we didn't find any */
114  Buffer = NULL;
115  BufferLength = 0;
116 
117  /* If we don't have IRPs, check if current buffer is big enough */
118  if (IsListEmpty(&NotifyChange->NotifyIrps))
119  {
120  if (NotifyChange->BufferLength >= NotifyChange->DataLength)
121  {
122  BufferLength = NotifyChange->BufferLength;
123  }
124  }
125  else
126  {
127  /* Otherwise, try to look at next IRP available */
128  NotifyIrp = CONTAINING_RECORD(NotifyChange->NotifyIrps.Flink, IRP, Tail.Overlay.ListEntry);
130 
131  /* If its buffer is big enough, get it */
132  if (Stack->Parameters.NotifyDirectory.Length >= NotifyChange->BufferLength)
133  {
134  /* Is it MDL? */
135  if (NotifyIrp->AssociatedIrp.SystemBuffer == NULL)
136  {
137  if (NotifyIrp->MdlAddress != NULL)
138  {
140  }
141  }
142  else
143  {
144  Buffer = NotifyIrp->AssociatedIrp.MasterIrp;
145  }
146 
147  /* Backup our accepted buffer length */
148  BufferLength = Stack->Parameters.NotifyDirectory.Length;
149  if (BufferLength > NotifyChange->BufferLength)
150  {
151  BufferLength = NotifyChange->BufferLength;
152  }
153  }
154  }
155 
156  /* At that point, we *may* have a buffer */
157 
158  /* If it has null length, then note that we won't use it */
159  if (BufferLength == 0)
160  {
161  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
162  }
163  else
164  {
165  /* If we have a buffer length, but no buffer then allocate one */
166  if (Buffer == NULL)
167  {
170  NotifyChange->AllocatedBuffer = Buffer;
171  }
172 
173  /* Copy data in that buffer */
174  RtlCopyMemory(Buffer, NotifyChange->Buffer, NotifyChange->DataLength);
175  NotifyChange->ThisBufferLength = BufferLength;
176  NotifyChange->Buffer = Buffer;
177  }
178 
179  /* If we have to notify immediately, ensure that any buffer is 0-ed out */
180  if (NotifyChange->Flags & NOTIFY_IMMEDIATELY)
181  {
182  NotifyChange->Buffer = 0;
183  NotifyChange->AllocatedBuffer = 0;
184  NotifyChange->LastEntry = 0;
185  NotifyChange->DataLength = 0;
186  NotifyChange->ThisBufferLength = 0;
187  }
188  }
189 
190  /* It's now time to complete - data are ready */
191 
192  /* Set appropriate status and complete */
193  Irp->IoStatus.Status = STATUS_CANCELLED;
195 
196  /* If that notification isn't referenced any longer, drop it */
197  if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
198  {
199  /* If it had an allocated buffer, delete */
200  if (NotifyChange->AllocatedBuffer)
201  {
202  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
204  }
205 
206  /* In case of full name, remember subject context for later deletion */
207  if (NotifyChange->FullDirectoryName)
208  {
209  SubjectContext = NotifyChange->SubjectContext;
210  }
211 
212  /* We mustn't have ANY change left anymore */
213  ASSERT(NotifyChange->NotifyList.Flink == NULL);
214  ExFreePoolWithTag(NotifyChange, 0);
215  }
216  }
218  {
219  FsRtlNotifyReleaseFastMutex(RealNotifySync);
220 
221  /* If the subject security context was captured, release and free it */
222  if (SubjectContext)
223  {
226  }
227  }
228  _SEH2_END;
229 }
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fltkernel.h:2239
VOID NTAPI SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:360
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
FORCEINLINE VOID FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:22
ULONG ThisBufferLength
Definition: fsrtl.h:92
PSTRING FullDirectoryName
Definition: fsrtl.h:82
_In_ PIRP Irp
Definition: csq.h:116
PVOID Buffer
Definition: fsrtl.h:90
ULONG ReferenceCount
Definition: fsrtl.h:95
PVOID AllocatedBuffer
Definition: fsrtl.h:89
IRP
Definition: iotypes.h:2463
IoSetCancelRoutine(Irp, CancelRoutine)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG DataLength
Definition: fsrtl.h:93
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_opt_ PIRP NotifyIrp
Definition: fsrtlfuncs.h:722
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
VOID NTAPI PsChargePoolQuota(IN PEPROCESS Process, IN POOL_TYPE PoolType, IN SIZE_T Amount)
Definition: quota.c:175
_In_ ULONG BufferLength
Definition: usbdlib.h:225
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
smooth NULL
Definition: ftsmooth.c:416
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
#define IoCompleteRequest
Definition: irp.c:1240
Definition: bufpool.h:45
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FORCEINLINE VOID FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:41
#define TAG_FS_NOTIFICATIONS
Definition: tag.h:53
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
PEPROCESS OwningProcess
Definition: fsrtl.h:96
ULONG BufferLength
Definition: fsrtl.h:91
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InterlockedDecrement
Definition: armddk.h:52
USHORT Flags
Definition: fsrtl.h:86
PREAL_NOTIFY_SYNC NotifySync
Definition: fsrtl.h:77
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
_SEH2_END
Definition: create.c:4424
struct _NOTIFY_CHANGE * PNOTIFY_CHANGE
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
_SEH2_FINALLY
Definition: create.c:4395
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
VOID NTAPI PsReturnProcessPagedPoolQuota(IN PEPROCESS Process, IN SIZE_T Amount)
Definition: quota.c:267
unsigned int ULONG
Definition: retypes.h:1
#define MmGetSystemAddressForMdl(Mdl)
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
IoMarkIrpPending(Irp)
signed int * PLONG
Definition: retypes.h:5
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG LastEntry
Definition: fsrtl.h:94

Referenced by FsRtlNotifySetCancelRoutine().

◆ FsRtlCheckNotifyForDelete()

VOID FsRtlCheckNotifyForDelete ( IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext 
)

Definition at line 235 of file notify.c.

237 {
238  PLIST_ENTRY NextEntry;
239  PNOTIFY_CHANGE NotifyChange;
240 
241  if (!IsListEmpty(NotifyList))
242  {
243  /* Browse the notifications list to find the matching entry */
244  for (NextEntry = NotifyList->Flink;
245  NextEntry != NotifyList;
246  NextEntry = NextEntry->Flink)
247  {
248  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
249  /* If the current record matches with the given context, it's the good one */
250  if (NotifyChange->FsContext == FsContext && !IsListEmpty(&(NotifyChange->NotifyIrps)))
251  {
253  }
254  }
255  }
256 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
PVOID FsContext
Definition: fsrtl.h:78
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange, IN NTSTATUS Status)
Definition: notify.c:394
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239

Referenced by FsRtlNotifyFilterChangeDirectory().

◆ FsRtlIsNotifyOnList()

PNOTIFY_CHANGE FsRtlIsNotifyOnList ( IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext 
)

Definition at line 262 of file notify.c.

264 {
265  PLIST_ENTRY NextEntry;
266  PNOTIFY_CHANGE NotifyChange;
267 
268  if (!IsListEmpty(NotifyList))
269  {
270  /* Browse the notifications list to find the matching entry */
271  for (NextEntry = NotifyList->Flink;
272  NextEntry != NotifyList;
273  NextEntry = NextEntry->Flink)
274  {
275  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
276  /* If the current record matches with the given context, it's the good one */
277  if (NotifyChange->FsContext == FsContext)
278  {
279  return NotifyChange;
280  }
281  }
282  }
283  return NULL;
284 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
PVOID FsContext
Definition: fsrtl.h:78
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239

Referenced by FsRtlNotifyCleanup(), and FsRtlNotifyFilterChangeDirectory().

◆ FsRtlNotifyAcquireFastMutex()

FORCEINLINE VOID FsRtlNotifyAcquireFastMutex ( IN PREAL_NOTIFY_SYNC  RealNotifySync)

Definition at line 22 of file notify.c.

23 {
24  ULONG_PTR CurrentThread = (ULONG_PTR)KeGetCurrentThread();
25 
26  /* Only acquire fast mutex if it's not already acquired by the current thread */
27  if (RealNotifySync->OwningThread != CurrentThread)
28  {
29  ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex));
30  RealNotifySync->OwningThread = CurrentThread;
31  }
32  /* Whatever the case, keep trace of the attempt to acquire fast mutex */
33  RealNotifySync->OwnerCount++;
34 }
uint32_t ULONG_PTR
Definition: typedefs.h:63
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ULONG_PTR
Definition: config.h:101
#define KeGetCurrentThread
Definition: hal.h:44

Referenced by FsRtlCancelNotify(), FsRtlNotifyCleanup(), FsRtlNotifyFilterChangeDirectory(), and FsRtlNotifyFilterReportChange().

◆ FsRtlNotifyChangeDirectory()

VOID NTAPI FsRtlNotifyChangeDirectory ( IN PNOTIFY_SYNC  NotifySync,
IN PVOID  FsContext,
IN PSTRING  FullDirectoryName,
IN PLIST_ENTRY  NotifyList,
IN BOOLEAN  WatchTree,
IN ULONG  CompletionFilter,
IN PIRP  NotifyIrp 
)

Definition at line 592 of file notify.c.

599 {
601  NotifyList,
602  FsContext,
604  WatchTree,
605  TRUE,
607  NotifyIrp,
608  NULL,
609  NULL,
610  NULL);
611 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
#define TRUE
Definition: types.h:120
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2239
_In_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_opt_ PIRP NotifyIrp
Definition: fsrtlfuncs.h:722
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING FullDirectoryName
Definition: fltkernel.h:2239
VOID NTAPI FsRtlNotifyFilterChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL, IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL)
Definition: notify.c:749

◆ FsRtlNotifyCleanup()

VOID NTAPI FsRtlNotifyCleanup ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext 
)

Definition at line 635 of file notify.c.

638 {
639  PNOTIFY_CHANGE NotifyChange;
640  PREAL_NOTIFY_SYNC RealNotifySync;
642 
643  /* Get real structure hidden behind the opaque pointer */
644  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
645 
646  /* Acquire the fast mutex */
647  FsRtlNotifyAcquireFastMutex(RealNotifySync);
648 
649  _SEH2_TRY
650  {
651  /* Find if there's a matching notification with the FsContext */
652  NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
653  if (NotifyChange)
654  {
655  /* Mark it as to know that cleanup is in process */
656  NotifyChange->Flags |= CLEANUP_IN_PROCESS;
657 
658  /* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP status */
659  if (!IsListEmpty(&NotifyChange->NotifyIrps))
660  {
662  }
663 
664  /* Decrease reference number and if 0 is reached, it's time to do complete cleanup */
665  if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
666  {
667  /* Remove it from the notifications list */
668  RemoveEntryList(&NotifyChange->NotifyList);
669 
670  /* In case there was an allocated buffer, free it */
671  if (NotifyChange->AllocatedBuffer)
672  {
673  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
674  ExFreePool(NotifyChange->AllocatedBuffer);
675  }
676 
677  /* In case there the string was set, get the captured subject security context */
678  if (NotifyChange->FullDirectoryName)
679  {
680  SubjectContext = NotifyChange->SubjectContext;
681  }
682 
683  /* Finally, free the notification, as it's not needed anymore */
684  ExFreePoolWithTag(NotifyChange, 'NrSF');
685  }
686  }
687  }
689  {
690  /* Release fast mutex */
691  FsRtlNotifyReleaseFastMutex(RealNotifySync);
692 
693  /* If the subject security context was captured, release and free it */
694  if (SubjectContext)
695  {
698  }
699  }
700  _SEH2_END;
701 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fltkernel.h:2239
VOID NTAPI SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:360
FORCEINLINE VOID FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:22
ULONG ThisBufferLength
Definition: fsrtl.h:92
PSTRING FullDirectoryName
Definition: fsrtl.h:82
ULONG ReferenceCount
Definition: fsrtl.h:95
PVOID AllocatedBuffer
Definition: fsrtl.h:89
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_SEH2_TRY
Definition: create.c:4250
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
struct _REAL_NOTIFY_SYNC * PREAL_NOTIFY_SYNC
VOID FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange, IN NTSTATUS Status)
Definition: notify.c:394
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
PNOTIFY_CHANGE FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:262
smooth NULL
Definition: ftsmooth.c:416
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
#define CLEANUP_IN_PROCESS
Definition: fsrtl.h:57
FORCEINLINE VOID FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:41
#define STATUS_NOTIFY_CLEANUP
Definition: ntstatus.h:90
PEPROCESS OwningProcess
Definition: fsrtl.h:96
#define InterlockedDecrement
Definition: armddk.h:52
USHORT Flags
Definition: fsrtl.h:86
_SEH2_END
Definition: create.c:4424
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239
_SEH2_FINALLY
Definition: create.c:4395
VOID NTAPI PsReturnProcessPagedPoolQuota(IN PEPROCESS Process, IN SIZE_T Amount)
Definition: quota.c:267
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
signed int * PLONG
Definition: retypes.h:5
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by _Dispatch_type_(), _Requires_lock_held_(), Ext2Cleanup(), FFSCleanup(), RfsdCleanup(), UDFCommonCleanup(), and VfatCleanupFile().

◆ FsRtlNotifyCompleteIrp()

VOID FsRtlNotifyCompleteIrp ( IN PIRP  Irp,
IN PNOTIFY_CHANGE  NotifyChange,
IN ULONG  DataLength,
IN NTSTATUS  Status,
IN BOOLEAN  SkipCompletion 
)

Definition at line 290 of file notify.c.

295 {
296  PVOID Buffer;
297  PIO_STACK_LOCATION Stack;
298 
299  PAGED_CODE();
300 
301  /* Check if we need to complete */
302  if (!FsRtlNotifySetCancelRoutine(Irp, NotifyChange) && SkipCompletion)
303  {
304  return;
305  }
306 
307  /* No succes => no data to return just complete */
308  if (Status != STATUS_SUCCESS)
309  {
310  goto Completion;
311  }
312 
313  /* Ensure there's something to return */
315  if (!DataLength || Stack->Parameters.NotifyDirectory.Length < DataLength)
316  {
318  goto Completion;
319  }
320 
321  /* Ensture there's a buffer where to find data */
322  if (!NotifyChange->AllocatedBuffer)
323  {
324  Irp->IoStatus.Information = DataLength;
325  NotifyChange->Buffer = NULL;
326  goto Completion;
327  }
328 
329  /* Now, browse all the way to return data
330  * and find the one that will work. We will
331  * return data whatever happens
332  */
333  if (Irp->AssociatedIrp.SystemBuffer)
334  {
335  Buffer = Irp->AssociatedIrp.SystemBuffer;
336  goto CopyAndComplete;
337  }
338 
339  if (Irp->MdlAddress)
340  {
341  Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
342  goto CopyAndComplete;
343  }
344 
345  if (!(Stack->Control & SL_PENDING_RETURNED))
346  {
347  Buffer = Irp->UserBuffer;
348  goto CopyAndComplete;
349  }
350 
352  Irp->AssociatedIrp.SystemBuffer = NotifyChange->AllocatedBuffer;
353  /* Nothing to copy */
354  goto ReleaseAndComplete;
355 
356 CopyAndComplete:
357  _SEH2_TRY
358  {
359  RtlCopyMemory(Buffer, NotifyChange->AllocatedBuffer, DataLength);
360  }
362  {
363  /* Do nothing */
364  }
365  _SEH2_END;
366 
367 ReleaseAndComplete:
368  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
369 
370  /* Release buffer UNLESS it's used */
371  if (NotifyChange->AllocatedBuffer != Irp->AssociatedIrp.SystemBuffer &&
372  NotifyChange->AllocatedBuffer)
373  {
374  ExFreePoolWithTag(NotifyChange->AllocatedBuffer, 0);
375  }
376 
377  /* Prepare for return */
378  NotifyChange->AllocatedBuffer = 0;
379  NotifyChange->ThisBufferLength = 0;
380  Irp->IoStatus.Information = DataLength;
381  NotifyChange->Buffer = NULL;
382 
383  /* Finally complete */
384 Completion:
386  Irp->IoStatus.Status = Status;
388 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define SL_PENDING_RETURNED
Definition: iotypes.h:2969
_In_ PIRP Irp
Definition: csq.h:116
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
Definition: bufpool.h:45
#define STATUS_NOTIFY_ENUM_DIR
Definition: ntstatus.h:91
Status
Definition: gdiplustypes.h:24
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
_SEH2_END
Definition: create.c:4424
#define IRP_BUFFERED_IO
BOOLEAN FsRtlNotifySetCancelRoutine(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
Definition: notify.c:424
#define IRP_DEALLOCATE_BUFFER
VOID NTAPI PsReturnProcessPagedPoolQuota(IN PEPROCESS Process, IN SIZE_T Amount)
Definition: quota.c:267
#define MmGetSystemAddressForMdl(Mdl)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
#define IRP_SYNCHRONOUS_PAGING_IO

Referenced by FsRtlNotifyCompleteIrpList(), and FsRtlNotifyFilterChangeDirectory().

◆ FsRtlNotifyCompleteIrpList()

VOID FsRtlNotifyCompleteIrpList ( IN PNOTIFY_CHANGE  NotifyChange,
IN NTSTATUS  Status 
)

Definition at line 394 of file notify.c.

396 {
397  PIRP Irp;
399  PLIST_ENTRY NextEntry;
400 
401  DataLength = NotifyChange->DataLength;
402 
403  NotifyChange->Flags &= (NOTIFY_IMMEDIATELY | WATCH_TREE);
404  NotifyChange->DataLength = 0;
405  NotifyChange->LastEntry = 0;
406 
407  while (!IsListEmpty(&(NotifyChange->NotifyIrps)))
408  {
409  /* We take the first entry */
410  NextEntry = RemoveHeadList(&(NotifyChange->NotifyIrps));
411  Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
412  /* We complete it */
413  FsRtlNotifyCompleteIrp(Irp, NotifyChange, DataLength, Status, TRUE);
414  /* If we're notifying success, just notify first one */
415  if (Status == STATUS_SUCCESS)
416  break;
417  }
418 }
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
IRP
Definition: iotypes.h:2463
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define WATCH_TREE
Definition: fsrtl.h:55
Definition: typedefs.h:117
VOID FsRtlNotifyCompleteIrp(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange, IN ULONG DataLength, IN NTSTATUS Status, IN BOOLEAN SkipCompletion)
Definition: notify.c:290
Status
Definition: gdiplustypes.h:24
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
return STATUS_SUCCESS
Definition: btrfs.c:2938

Referenced by FsRtlCheckNotifyForDelete(), FsRtlNotifyCleanup(), and FsRtlNotifyFilterReportChange().

◆ FsRtlNotifyFilterChangeDirectory()

VOID NTAPI FsRtlNotifyFilterChangeDirectory ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext,
IN PSTRING  FullDirectoryName,
IN BOOLEAN  WatchTree,
IN BOOLEAN  IgnoreBuffer,
IN ULONG  CompletionFilter,
IN PIRP  NotifyIrp,
IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback  OPTIONAL,
IN PSECURITY_SUBJECT_CONTEXT SubjectContext  OPTIONAL,
IN PFILTER_REPORT_CHANGE FilterCallback  OPTIONAL 
)

Definition at line 749 of file notify.c.

760 {
761  ULONG SavedLength;
762  PIO_STACK_LOCATION Stack;
763  PNOTIFY_CHANGE NotifyChange = NULL;
764  PREAL_NOTIFY_SYNC RealNotifySync;
765 
766  PAGED_CODE();
767 
768  DPRINT("FsRtlNotifyFilterChangeDirectory(): %p, %p, %p, %wZ, %u, %u, %u, %p, %p, %p, %p\n",
771 
772  /* Get real structure hidden behind the opaque pointer */
773  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
774 
775  /* Acquire the fast mutex */
776  FsRtlNotifyAcquireFastMutex(RealNotifySync);
777 
778  _SEH2_TRY
779  {
780  /* If we have no IRP, FSD is performing a cleanup */
781  if (!NotifyIrp)
782  {
783  /* So, we delete */
785  _SEH2_LEAVE;
786  }
787 
788  NotifyIrp->IoStatus.Status = STATUS_SUCCESS;
789  NotifyIrp->IoStatus.Information = (ULONG_PTR)NULL;
790 
792  /* If FileObject's been cleaned up, just return */
793  if (Stack->FileObject->Flags & FO_CLEANUP_COMPLETE)
794  {
796  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
798  _SEH2_LEAVE;
799  }
800 
801  /* Try to find a matching notification has been already registered */
802  NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
803  if (NotifyChange)
804  {
805  /* If it's been found, and is cleaned up, immediatly complete */
806  if (NotifyChange->Flags & CLEANUP_IN_PROCESS)
807  {
809  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
811  }
812  /* Or if it's about to be deleted, complete */
813  else if (NotifyChange->Flags & DELETE_IN_PROCESS)
814  {
816  NotifyIrp->IoStatus.Status = STATUS_DELETE_PENDING;
818  }
819  /* Complete now if asked to (and not asked to notify later on) */
820  if ((NotifyChange->Flags & NOTIFY_IMMEDIATELY) && !(NotifyChange->Flags & NOTIFY_LATER))
821  {
822  NotifyChange->Flags &= ~NOTIFY_IMMEDIATELY;
824  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_ENUM_DIR;
826  }
827  /* If no data yet, or asked to notify later on, handle */
828  else if (NotifyChange->DataLength == 0 || (NotifyChange->Flags & NOTIFY_LATER))
829  {
830  goto HandleIRP;
831  }
832  /* Else, just complete with we have */
833  else
834  {
835  SavedLength = NotifyChange->DataLength;
836  NotifyChange->DataLength = 0;
837  FsRtlNotifyCompleteIrp(NotifyIrp, NotifyChange, SavedLength, STATUS_SUCCESS, FALSE);
838  }
839 
840  _SEH2_LEAVE;
841  }
842 
843  /* Allocate new notification */
845  sizeof(NOTIFY_CHANGE), 'NrSF');
846  RtlZeroMemory(NotifyChange, sizeof(NOTIFY_CHANGE));
847 
848  /* Set basic information */
849  NotifyChange->NotifySync = NotifySync;
850  NotifyChange->FsContext = FsContext;
851  NotifyChange->StreamID = Stack->FileObject->FsContext;
852  NotifyChange->TraverseCallback = TraverseCallback;
853  NotifyChange->SubjectContext = SubjectContext;
854  NotifyChange->FullDirectoryName = FullDirectoryName;
855  NotifyChange->FilterCallback = FilterCallback;
856  InitializeListHead(&(NotifyChange->NotifyIrps));
857 
858  /* Keep trace of WatchTree */
859  if (WatchTree)
860  {
861  NotifyChange->Flags |= WATCH_TREE;
862  }
863 
864  /* If string is empty, faulty to ANSI */
865  if (FullDirectoryName->Length == 0)
866  {
867  NotifyChange->CharacterSize = sizeof(CHAR);
868  }
869  else
870  {
871  /* If it can't contain WCHAR, it's ANSI */
872  if (FullDirectoryName->Length < sizeof(WCHAR) || ((CHAR*)FullDirectoryName->Buffer)[1] != 0)
873  {
874  NotifyChange->CharacterSize = sizeof(CHAR);
875  }
876  else
877  {
878  NotifyChange->CharacterSize = sizeof(WCHAR);
879  }
880 
881  /* Now, check is user is willing to watch root */
882  if (FullDirectoryName->Length == NotifyChange->CharacterSize)
883  {
884  NotifyChange->Flags |= WATCH_ROOT;
885  }
886  }
887 
888  NotifyChange->CompletionFilter = CompletionFilter;
889 
890  /* In case we have not to ignore buffer , keep its length */
891  if (!IgnoreBuffer)
892  {
893  NotifyChange->BufferLength = Stack->Parameters.NotifyDirectory.Length;
894  }
895 
896  NotifyChange->OwningProcess = NotifyIrp->Tail.Overlay.Thread->ThreadsProcess;
897 
898  /* Insert the notification into the notification list */
899  InsertTailList(NotifyList, &(NotifyChange->NotifyList));
900 
901  NotifyChange->ReferenceCount = 1;
902 
903 HandleIRP:
904  /* Associate the notification to the IRP */
905  NotifyIrp->IoStatus.Information = (ULONG_PTR)NotifyChange;
906  /* The IRP is pending */
908  /* Insert the IRP in the IRP list */
909  InsertTailList(&(NotifyChange->NotifyIrps), &(NotifyIrp->Tail.Overlay.ListEntry));
910  /* Increment reference count */
911  InterlockedIncrement((PLONG)&(NotifyChange->ReferenceCount));
912  /* Set cancel routine to FsRtl one */
914  }
916  {
917  /* Release fast mutex */
918  FsRtlNotifyReleaseFastMutex(RealNotifySync);
919 
920  /* If the subject security context was captured and there's no notify */
921  if (SubjectContext && (!NotifyChange || NotifyChange->FullDirectoryName))
922  {
925  }
926  }
927  _SEH2_END;
928 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fltkernel.h:2239
VOID NTAPI SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:360
PVOID FsContext
Definition: fsrtl.h:78
#define WATCH_ROOT
Definition: fsrtl.h:59
FORCEINLINE VOID FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:22
PSTRING FullDirectoryName
Definition: fsrtl.h:82
PVOID StreamID
Definition: fsrtl.h:79
char CHAR
Definition: xmlstorage.h:175
PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback
Definition: fsrtl.h:80
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2239
ULONG ReferenceCount
Definition: fsrtl.h:95
#define InsertTailList(ListHead, Entry)
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT _In_opt_ PFILTER_REPORT_CHANGE FilterCallback
Definition: fltkernel.h:2239
#define PAGED_CODE()
Definition: video.h:57
ULONG DataLength
Definition: fsrtl.h:93
_SEH2_TRY
Definition: create.c:4250
_In_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_opt_ PIRP NotifyIrp
Definition: fsrtlfuncs.h:722
struct _REAL_NOTIFY_SYNC * PREAL_NOTIFY_SYNC
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN IgnoreBuffer
Definition: fltkernel.h:2239
PNOTIFY_CHANGE FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:262
smooth NULL
Definition: ftsmooth.c:416
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
#define IoCompleteRequest
Definition: irp.c:1240
#define CLEANUP_IN_PROCESS
Definition: fsrtl.h:57
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_NOTIFY_ENUM_DIR
Definition: ntstatus.h:91
FORCEINLINE VOID FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:41
#define WATCH_TREE
Definition: fsrtl.h:55
#define DELETE_IN_PROCESS
Definition: fsrtl.h:60
__wchar_t WCHAR
Definition: xmlstorage.h:180
PFILTER_REPORT_CHANGE FilterCallback
Definition: fsrtl.h:85
#define NOTIFY_LATER
Definition: fsrtl.h:58
#define STATUS_NOTIFY_CLEANUP
Definition: ntstatus.h:90
VOID FsRtlCheckNotifyForDelete(IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:235
PEPROCESS OwningProcess
Definition: fsrtl.h:96
ULONG BufferLength
Definition: fsrtl.h:91
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT Flags
Definition: fsrtl.h:86
PREAL_NOTIFY_SYNC NotifySync
Definition: fsrtl.h:77
VOID FsRtlNotifyCompleteIrp(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange, IN ULONG DataLength, IN NTSTATUS Status, IN BOOLEAN SkipCompletion)
Definition: notify.c:290
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
#define InterlockedIncrement
Definition: armddk.h:53
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1747
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239
_SEH2_FINALLY
Definition: create.c:4395
BOOLEAN FsRtlNotifySetCancelRoutine(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
Definition: notify.c:424
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2239
UCHAR CharacterSize
Definition: fsrtl.h:87
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback
Definition: fltkernel.h:2239
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define _SEH2_LEAVE
Definition: filesup.c:20
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
ULONG CompletionFilter
Definition: fsrtl.h:88
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
signed int * PLONG
Definition: retypes.h:5
#define CHAR(Char)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING FullDirectoryName
Definition: fltkernel.h:2239

Referenced by FsRtlNotifyChangeDirectory(), FsRtlNotifyFullChangeDirectory(), and notify_change_directory().

◆ FsRtlNotifyFilterReportChange()

VOID NTAPI FsRtlNotifyFilterReportChange ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PSTRING  FullTargetName,
IN USHORT  TargetNameOffset,
IN PSTRING StreamName  OPTIONAL,
IN PSTRING NormalizedParentName  OPTIONAL,
IN ULONG  FilterMatch,
IN ULONG  Action,
IN PVOID  TargetContext,
IN PVOID  FilterContext 
)

Definition at line 973 of file notify.c.

983 {
984  PIRP Irp;
986  USHORT FullPosition;
987  PLIST_ENTRY NextEntry;
988  PIO_STACK_LOCATION Stack;
989  PNOTIFY_CHANGE NotifyChange;
990  PREAL_NOTIFY_SYNC RealNotifySync;
991  PFILE_NOTIFY_INFORMATION FileNotifyInfo;
992  BOOLEAN IsStream, IsParent, PoolQuotaCharged;
993  STRING TargetDirectory, TargetName, ParentName, IntNormalizedParentName;
994  ULONG NumberOfBytes, TargetNumberOfParts, FullNumberOfParts, LastPartOffset, ParentNameOffset, ParentNameLength;
995  ULONG DataLength, AlignedDataLength;
996 
997  TargetDirectory.Length = 0;
998  TargetDirectory.MaximumLength = 0;
999  TargetDirectory.Buffer = NULL;
1000  TargetName.Length = 0;
1001  TargetName.MaximumLength = 0;
1002  TargetName.Buffer = NULL;
1003  ParentName.Length = 0;
1004  ParentName.MaximumLength = 0;
1005  ParentName.Buffer = NULL;
1006  IsStream = FALSE;
1007 
1008  PAGED_CODE();
1009 
1010  DPRINT("FsRtlNotifyFilterReportChange(%p, %p, %p, %u, %p, %p, %p, %x, %x, %p, %p)\n",
1013 
1014  /* We need offset in name */
1016  {
1017  return;
1018  }
1019 
1020  /* Get real structure hidden behind the opaque pointer */
1021  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
1022  /* Acquire lock - will be released in finally block */
1023  FsRtlNotifyAcquireFastMutex(RealNotifySync);
1024  _SEH2_TRY
1025  {
1026  /* Browse all the registered notifications we have */
1027  for (NextEntry = NotifyList->Flink; NextEntry != NotifyList;
1028  NextEntry = NextEntry->Flink)
1029  {
1030  /* Try to find an entry matching our change */
1031  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
1032  if (FullTargetName != NULL)
1033  {
1034  ASSERT(NotifyChange->FullDirectoryName != NULL);
1035  if (!NotifyChange->FullDirectoryName->Length)
1036  {
1037  continue;
1038  }
1039 
1040  if (!(FilterMatch & NotifyChange->CompletionFilter))
1041  {
1042  continue;
1043  }
1044 
1045  /* If no normalized name provided, construct it from full target name */
1046  if (NormalizedParentName == NULL)
1047  {
1048  IntNormalizedParentName.Buffer = FullTargetName->Buffer;
1049  if (TargetNameOffset != NotifyChange->CharacterSize)
1050  {
1051  IntNormalizedParentName.MaximumLength =
1052  IntNormalizedParentName.Length = TargetNameOffset - NotifyChange->CharacterSize;
1053  }
1054  else
1055  {
1056  IntNormalizedParentName.MaximumLength =
1057  IntNormalizedParentName.Length = TargetNameOffset;
1058  }
1059  NormalizedParentName = &IntNormalizedParentName;
1060  }
1061 
1062  /* heh? Watched directory bigger than changed file? */
1063  if (NormalizedParentName->Length < NotifyChange->FullDirectoryName->Length)
1064  {
1065  continue;
1066  }
1067 
1068  /* Same len => parent */
1069  if (NormalizedParentName->Length == NotifyChange->FullDirectoryName->Length)
1070  {
1071  IsParent = TRUE;
1072  }
1073  /* If not, then, we have to be watching the tree, otherwise we don't have to report such changes */
1074  else if (!(NotifyChange->Flags & WATCH_TREE))
1075  {
1076  continue;
1077  }
1078  /* And finally, we've to check we're properly \-terminated */
1079  else
1080  {
1081  if (!(NotifyChange->Flags & WATCH_ROOT))
1082  {
1083  if (NotifyChange->CharacterSize == sizeof(CHAR))
1084  {
1085  if (((PSTR)NormalizedParentName->Buffer)[NotifyChange->FullDirectoryName->Length] != '\\')
1086  {
1087  continue;
1088  }
1089  }
1090  else
1091  {
1092  if (((PWSTR)NormalizedParentName->Buffer)[NotifyChange->FullDirectoryName->Length / sizeof (WCHAR)] != L'\\')
1093  {
1094  continue;
1095  }
1096  }
1097  }
1098 
1099  IsParent = FALSE;
1100  }
1101 
1102  /* If len matches, then check that both name are equal */
1103  if (!RtlEqualMemory(NormalizedParentName->Buffer, NotifyChange->FullDirectoryName->Buffer,
1104  NotifyChange->FullDirectoryName->Length))
1105  {
1106  continue;
1107  }
1108 
1109  /* Call traverse callback (only if we have to traverse ;-)) */
1110  if (!IsParent
1111  && NotifyChange->TraverseCallback != NULL
1112  && !NotifyChange->TraverseCallback(NotifyChange->FsContext,
1113  TargetContext,
1114  NotifyChange->SubjectContext))
1115  {
1116  continue;
1117  }
1118 
1119  /* And then, filter callback if provided */
1120  if (NotifyChange->FilterCallback != NULL
1121  && FilterContext != NULL
1122  && !NotifyChange->FilterCallback(NotifyChange->FsContext, FilterContext))
1123  {
1124  continue;
1125  }
1126  }
1127  /* We have a stream! */
1128  else
1129  {
1130  ASSERT(NotifyChange->FullDirectoryName == NULL);
1131  if (TargetContext != NotifyChange->SubjectContext)
1132  {
1133  continue;
1134  }
1135 
1136  ParentName.Buffer = NULL;
1137  ParentName.Length = 0;
1138  IsStream = TRUE;
1139  IsParent = FALSE;
1140  }
1141 
1142  /* If we don't have to notify immediately, prepare for output */
1143  if (!(NotifyChange->Flags & NOTIFY_IMMEDIATELY))
1144  {
1145  /* If we have something to output... */
1146  if (NotifyChange->BufferLength)
1147  {
1148  /* Get size of the output */
1149  NumberOfBytes = 0;
1150  Irp = NULL;
1151  if (!NotifyChange->ThisBufferLength)
1152  {
1153  if (IsListEmpty(&NotifyChange->NotifyIrps))
1154  {
1155  NumberOfBytes = NotifyChange->BufferLength;
1156  }
1157  else
1158  {
1159  Irp = CONTAINING_RECORD(NotifyChange->NotifyIrps.Flink, IRP, Tail.Overlay.ListEntry);
1161  NumberOfBytes = Stack->Parameters.NotifyDirectory.Length;
1162  }
1163  }
1164  else
1165  {
1166  NumberOfBytes = NotifyChange->ThisBufferLength;
1167  }
1168 
1169  /* If we're matching parent, we don't care about parent (redundant) */
1170  if (IsParent)
1171  {
1172  ParentName.Length = 0;
1173  }
1174  else
1175  {
1176  /* If we don't deal with streams, some more work is required */
1177  if (!IsStream)
1178  {
1179  if (NotifyChange->Flags & WATCH_ROOT ||
1180  (NormalizedParentName->Buffer != FullTargetName->Buffer))
1181  {
1182  /* Construct TargetDirectory if we don't have it yet */
1183  if (TargetDirectory.Buffer == NULL)
1184  {
1185  TargetDirectory.Buffer = FullTargetName->Buffer;
1186  TargetDirectory.Length = TargetNameOffset;
1187  if (TargetNameOffset != NotifyChange->CharacterSize)
1188  {
1189  TargetDirectory.Length = TargetNameOffset - NotifyChange->CharacterSize;
1190  }
1191  TargetDirectory.MaximumLength = TargetDirectory.Length;
1192  }
1193  /* Now, we start looking for matching parts (unless we watch root) */
1194  TargetNumberOfParts = 0;
1195  if (!(NotifyChange->Flags & WATCH_ROOT))
1196  {
1197  FullNumberOfParts = 1;
1198  if (NotifyChange->CharacterSize == sizeof(CHAR))
1199  {
1201  TargetDirectory.Length, PSTR, '\\');
1202  }
1203  else
1204  {
1206  TargetDirectory.Length / sizeof(WCHAR), PWSTR, L'\\');
1207  LastPartOffset *= NotifyChange->CharacterSize;
1208  }
1209  }
1210 
1211  /* Then, we can construct proper parent name */
1212  ParentNameOffset = NotifyChange->CharacterSize + LastPartOffset;
1213  ParentName.Buffer = &TargetDirectory.Buffer[ParentNameOffset];
1214  ParentNameLength = TargetDirectory.Length;
1215  }
1216  else
1217  {
1218  /* Construct parent name even for streams */
1219  ParentName.Buffer = &NormalizedParentName->Buffer[NotifyChange->FullDirectoryName->Length] + NotifyChange->CharacterSize;
1220  ParentNameLength = NormalizedParentName->Length - NotifyChange->FullDirectoryName->Length;
1221  ParentNameOffset = NotifyChange->CharacterSize;
1222  }
1223  ParentNameLength -= ParentNameOffset;
1224  ParentName.Length = ParentNameLength;
1225  ParentName.MaximumLength = ParentNameLength;
1226  }
1227  }
1228 
1229  /* Start to count amount of data to write, we've first the structure itself */
1231 
1232  /* If stream, we'll just append stream name */
1233  if (IsStream)
1234  {
1235  ASSERT(StreamName != NULL);
1236  DataLength += StreamName->Length;
1237  }
1238  else
1239  {
1240  /* If not parent, we've to append parent name */
1241  if (!IsParent)
1242  {
1243  if (NotifyChange->CharacterSize == sizeof(CHAR))
1244  {
1246  }
1247  else
1248  {
1249  DataLength += ParentName.Length;
1250  }
1251  DataLength += sizeof(WCHAR);
1252  }
1253 
1254  /* Look for target name & construct it, if required */
1255  if (TargetName.Buffer == NULL)
1256  {
1257  TargetName.Buffer = &FullTargetName->Buffer[TargetNameOffset];
1258  TargetName.Length =
1259  TargetName.MaximumLength = FullTargetName->Length - TargetNameOffset;
1260  }
1261 
1262  /* Then, we will append it as well */
1263  if (NotifyChange->CharacterSize == sizeof(CHAR))
1264  {
1266  }
1267  else
1268  {
1269  DataLength += TargetName.Length;
1270  }
1271 
1272  /* If we also had a stream name, then we can append it as well */
1273  if (StreamName != NULL)
1274  {
1275  if (NotifyChange->CharacterSize == sizeof(WCHAR))
1276  {
1277  DataLength += StreamName->Length + sizeof(WCHAR);
1278  }
1279  else
1280  {
1282  }
1283  }
1284  }
1285 
1286  /* Get the position where we can put our data (aligned!) */
1287  AlignedDataLength = ROUND_UP(NotifyChange->DataLength, sizeof(ULONG));
1288  /* If it's higher than buffer length, then, bail out without outputing */
1289  if (DataLength > NumberOfBytes || AlignedDataLength + DataLength > NumberOfBytes)
1290  {
1291  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1292  }
1293  else
1294  {
1295  OutputBuffer = NULL;
1296  FileNotifyInfo = NULL;
1297  /* If we already had a buffer, update last entry position */
1298  if (NotifyChange->Buffer != NULL)
1299  {
1300  FileNotifyInfo = (PVOID)((ULONG_PTR)NotifyChange->Buffer + NotifyChange->LastEntry);
1301  FileNotifyInfo->NextEntryOffset = AlignedDataLength - NotifyChange->LastEntry;
1302  NotifyChange->LastEntry = AlignedDataLength;
1303  /* And get our output buffer */
1304  OutputBuffer = (PVOID)((ULONG_PTR)NotifyChange->Buffer + AlignedDataLength);
1305  }
1306  /* If we hadn't buffer, try to find one */
1307  else if (Irp != NULL)
1308  {
1309  if (Irp->AssociatedIrp.SystemBuffer != NULL)
1310  {
1311  OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
1312  }
1313  else if (Irp->MdlAddress != NULL)
1314  {
1315  OutputBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1316  }
1317 
1318  NotifyChange->Buffer = OutputBuffer;
1319  NotifyChange->ThisBufferLength = NumberOfBytes;
1320  }
1321 
1322  /* If we couldn't find one, then allocate one */
1323  if (NotifyChange->Buffer == NULL)
1324  {
1325  PoolQuotaCharged = FALSE;
1326  _SEH2_TRY
1327  {
1329  PoolQuotaCharged = TRUE;
1332  NotifyChange->Buffer = OutputBuffer;
1333  NotifyChange->AllocatedBuffer = OutputBuffer;
1334  }
1335  /* If something went wrong during allocation, notify immediately instead of outputing */
1337  {
1338  if (PoolQuotaCharged)
1339  {
1341  }
1342  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1343  }
1344  _SEH2_END;
1345  }
1346 
1347  /* Finally, if we have a buffer, fill it in! */
1348  if (OutputBuffer != NULL)
1349  {
1351  Action, &ParentName, &TargetName,
1352  StreamName, NotifyChange->CharacterSize == sizeof(WCHAR),
1353  DataLength))
1354  {
1355  NotifyChange->DataLength = DataLength + AlignedDataLength;
1356  }
1357  /* If it failed, notify immediately */
1358  else
1359  {
1360  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1361  }
1362  }
1363  }
1364 
1365  /* If we have to notify right now (something went wrong?) */
1366  if (NotifyChange->Flags & NOTIFY_IMMEDIATELY)
1367  {
1368  /* Ensure that all our buffers are NULL */
1369  if (NotifyChange->Buffer != NULL)
1370  {
1371  if (NotifyChange->AllocatedBuffer != NULL)
1372  {
1373  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
1375  }
1376 
1377  NotifyChange->Buffer = NULL;
1378  NotifyChange->AllocatedBuffer = NULL;
1379  NotifyChange->LastEntry = 0;
1380  NotifyChange->DataLength = 0;
1381  NotifyChange->ThisBufferLength = 0;
1382  }
1383  }
1384  }
1385  }
1386 
1387  /* If asking for old name in case of a rename, notify later on,
1388  * so that we can wait for new name.
1389  * http://msdn.microsoft.com/en-us/library/dn392331.aspx
1390  */
1392  {
1393  NotifyChange->Flags |= NOTIFY_LATER;
1394  }
1395  else
1396  {
1397  NotifyChange->Flags &= ~NOTIFY_LATER;
1398  if (!IsListEmpty(&NotifyChange->NotifyIrps))
1399  {
1401  }
1402  }
1403  }
1404  }
1406  {
1407  FsRtlNotifyReleaseFastMutex(RealNotifySync);
1408  }
1409  _SEH2_END;
1410 }
PVOID FsContext
Definition: fsrtl.h:78
#define TRUE
Definition: types.h:120
#define WATCH_ROOT
Definition: fsrtl.h:59
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define FILE_ACTION_RENAMED_OLD_NAME
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG _In_opt_ PVOID _In_opt_ PVOID FilterContext
Definition: fsrtlfuncs.h:738
FORCEINLINE VOID FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:22
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
ULONG ThisBufferLength
Definition: fsrtl.h:92
PSTRING FullDirectoryName
Definition: fsrtl.h:82
_In_ PIRP Irp
Definition: csq.h:116
uint16_t * PWSTR
Definition: typedefs.h:54
char CHAR
Definition: xmlstorage.h:175
PVOID Buffer
Definition: fsrtl.h:90
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING NormalizedParentName
Definition: fsrtlfuncs.h:738
PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback
Definition: fsrtl.h:80
unsigned short Length
Definition: sprintf.c:451
PVOID AllocatedBuffer
Definition: fsrtl.h:89
IRP
Definition: iotypes.h:2463
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN FsRtlNotifyUpdateBuffer(OUT PFILE_NOTIFY_INFORMATION OutputBuffer, IN ULONG Action, IN PSTRING ParentName, IN PSTRING TargetName, IN PSTRING StreamName, IN BOOLEAN IsUnicode, IN ULONG DataLength)
Definition: notify.c:473
#define PAGED_CODE()
Definition: video.h:57
ULONG DataLength
Definition: fsrtl.h:93
_SEH2_TRY
Definition: create.c:4250
_In_ PLIST_ENTRY _In_ PSTRING FullTargetName
Definition: fsrtlfuncs.h:738
uint32_t ULONG_PTR
Definition: typedefs.h:63
struct _REAL_NOTIFY_SYNC * PREAL_NOTIFY_SYNC
void * Buffer
Definition: sprintf.c:453
VOID FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange, IN NTSTATUS Status)
Definition: notify.c:394
VOID NTAPI PsChargePoolQuota(IN PEPROCESS Process, IN POOL_TYPE PoolType, IN SIZE_T Amount)
Definition: quota.c:175
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
void DPRINT(...)
Definition: polytest.cpp:61
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FORCEINLINE VOID FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
Definition: notify.c:41
#define TAG_FS_NOTIFICATIONS
Definition: tag.h:53
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING StreamName
Definition: fsrtlfuncs.h:738
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define WATCH_TREE
Definition: fsrtl.h:55
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG FilterMatch
Definition: fsrtlfuncs.h:738
__wchar_t WCHAR
Definition: xmlstorage.h:180
PFILTER_REPORT_CHANGE FilterCallback
Definition: fsrtl.h:85
#define NOTIFY_LATER
Definition: fsrtl.h:58
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG Action
Definition: fsrtlfuncs.h:738
PEPROCESS OwningProcess
Definition: fsrtl.h:96
ULONG BufferLength
Definition: fsrtl.h:91
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
std::wstring STRING
Definition: fontsub.cpp:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const WCHAR L[]
Definition: oid.c:1250
USHORT Flags
Definition: fsrtl.h:86
WCHAR TargetName[256]
Definition: arping.c:27
Definition: typedefs.h:117
#define FsRtlNotifyGetLastPartOffset(FullLen, TargLen, Type, Chr)
Definition: notify.c:52
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG _In_opt_ PVOID TargetContext
Definition: fsrtlfuncs.h:738
_SEH2_END
Definition: create.c:4424
unsigned short USHORT
Definition: pedump.c:61
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT TargetNameOffset
Definition: fsrtlfuncs.h:738
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239
signed char * PSTR
Definition: retypes.h:7
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
_SEH2_FINALLY
Definition: create.c:4395
UCHAR CharacterSize
Definition: fsrtl.h:87
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:998
VOID NTAPI PsReturnProcessPagedPoolQuota(IN PEPROCESS Process, IN SIZE_T Amount)
Definition: quota.c:267
unsigned int ULONG
Definition: retypes.h:1
#define MmGetSystemAddressForMdl(Mdl)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
return STATUS_SUCCESS
Definition: btrfs.c:2938
ULONG CompletionFilter
Definition: fsrtl.h:88
#define CHAR(Char)
#define RtlOemStringToCountedUnicodeSize(STRING)
ULONG LastEntry
Definition: fsrtl.h:94

Referenced by FsRtlNotifyFullReportChange(), FsRtlNotifyReportChange(), send_notification_fcb(), send_notification_fileref(), and set_rename_information().

◆ FsRtlNotifyFullChangeDirectory()

VOID NTAPI FsRtlNotifyFullChangeDirectory ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext,
IN PSTRING  FullDirectoryName,
IN BOOLEAN  WatchTree,
IN BOOLEAN  IgnoreBuffer,
IN ULONG  CompletionFilter,
IN PIRP  NotifyIrp,
IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback  OPTIONAL,
IN PSECURITY_SUBJECT_CONTEXT SubjectContext  OPTIONAL 
)

Definition at line 1458 of file notify.c.

1468 {
1470  NotifyList,
1471  FsContext,
1473  WatchTree,
1474  IgnoreBuffer,
1476  NotifyIrp,
1479  NULL);
1480 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2239
_In_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_opt_ PIRP NotifyIrp
Definition: fsrtlfuncs.h:722
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN IgnoreBuffer
Definition: fltkernel.h:2239
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback
Definition: fltkernel.h:2239
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING FullDirectoryName
Definition: fltkernel.h:2239
VOID NTAPI FsRtlNotifyFilterChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL, IN PFILTER_REPORT_CHANGE FilterCallback OPTIONAL)
Definition: notify.c:749

Referenced by _Requires_lock_held_(), Ext2Cleanup(), Ext2IsFileRemovable(), Ext2NotifyChangeDirectory(), FFSCleanup(), FFSNotifyChangeDirectory(), FFSSetDispositionInfo(), RfsdCleanup(), RfsdNotifyChangeDirectory(), RfsdSetDispositionInfo(), set_disposition_information(), UDFCommonCleanup(), UDFNotifyChangeDirectory(), UDFSetDispositionInformation(), and VfatNotifyChangeDirectory().

◆ FsRtlNotifyFullReportChange()

VOID NTAPI FsRtlNotifyFullReportChange ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PSTRING  FullTargetName,
IN USHORT  TargetNameOffset,
IN PSTRING StreamName  OPTIONAL,
IN PSTRING NormalizedParentName  OPTIONAL,
IN ULONG  FilterMatch,
IN ULONG  Action,
IN PVOID  TargetContext 
)

Definition at line 1523 of file notify.c.

1532 {
1533  FsRtlNotifyFilterReportChange(NotifySync,
1534  NotifyList,
1537  StreamName,
1539  FilterMatch,
1540  Action,
1541  TargetContext,
1542  NULL);
1543 }
VOID NTAPI FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
Definition: notify.c:973
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING NormalizedParentName
Definition: fsrtlfuncs.h:738
_In_ PLIST_ENTRY _In_ PSTRING FullTargetName
Definition: fsrtlfuncs.h:738
smooth NULL
Definition: ftsmooth.c:416
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING StreamName
Definition: fsrtlfuncs.h:738
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG FilterMatch
Definition: fsrtlfuncs.h:738
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG Action
Definition: fsrtlfuncs.h:738
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG _In_opt_ PVOID TargetContext
Definition: fsrtlfuncs.h:738
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT TargetNameOffset
Definition: fsrtlfuncs.h:738
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239

Referenced by Ext2NotifyReportChange(), FFSNotifyReportChange(), RfsdNotifyReportChange(), UDFHardLink(), UDFNotifyFullReportChange(), UDFRename(), and vfatReportChange().

◆ FsRtlNotifyInitializeSync()

VOID NTAPI FsRtlNotifyInitializeSync ( IN PNOTIFY_SYNC NotifySync)

Definition at line 1561 of file notify.c.

1562 {
1563  PREAL_NOTIFY_SYNC RealNotifySync;
1564 
1565  *NotifySync = NULL;
1566 
1568  sizeof(REAL_NOTIFY_SYNC), 'SNSF');
1569  ExInitializeFastMutex(&(RealNotifySync->FastMutex));
1570  RealNotifySync->OwningThread = 0;
1571  RealNotifySync->OwnerCount = 0;
1572 
1573  *NotifySync = RealNotifySync;
1574 }
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
ULONG_PTR OwningThread
Definition: fsrtl.h:68
#define POOL_RAISE_IF_ALLOCATION_FAILURE
ULONG OwnerCount
Definition: fsrtl.h:69
FAST_MUTEX FastMutex
Definition: fsrtl.h:67

Referenced by _Requires_lock_held_(), CdInitializeVcb(), Ext2InitializeVcb(), FFSInitializeVcb(), mount_vol(), RfsdInitializeVcb(), UDFInitializeVCB(), and VfatMount().

◆ FsRtlNotifyReleaseFastMutex()

FORCEINLINE VOID FsRtlNotifyReleaseFastMutex ( IN PREAL_NOTIFY_SYNC  RealNotifySync)

Definition at line 41 of file notify.c.

42 {
43  RealNotifySync->OwnerCount--;
44  /* Release the fast mutex only if no other instance needs it */
45  if (!RealNotifySync->OwnerCount)
46  {
47  ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
48  RealNotifySync->OwningThread = (ULONG_PTR)0;
49  }
50 }
VOID FASTCALL ExReleaseFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:86
#define ULONG_PTR
Definition: config.h:101

Referenced by FsRtlCancelNotify(), FsRtlNotifyCleanup(), FsRtlNotifyFilterChangeDirectory(), and FsRtlNotifyFilterReportChange().

◆ FsRtlNotifyReportChange()

VOID NTAPI FsRtlNotifyReportChange ( IN PNOTIFY_SYNC  NotifySync,
IN PLIST_ENTRY  NotifyList,
IN PSTRING  FullTargetName,
IN PUSHORT  FileNamePartLength,
IN ULONG  FilterMatch 
)

Definition at line 1604 of file notify.c.

1609 {
1610  FsRtlNotifyFilterReportChange(NotifySync,
1611  NotifyList,
1613  FullTargetName->Length - *FileNamePartLength,
1614  NULL,
1615  NULL,
1616  FilterMatch,
1617  0,
1618  NULL,
1619  NULL);
1620 }
VOID NTAPI FsRtlNotifyFilterReportChange(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PSTRING FullTargetName, IN USHORT TargetNameOffset, IN PSTRING StreamName OPTIONAL, IN PSTRING NormalizedParentName OPTIONAL, IN ULONG FilterMatch, IN ULONG Action, IN PVOID TargetContext, IN PVOID FilterContext)
Definition: notify.c:973
_In_ PLIST_ENTRY _In_ PSTRING FullTargetName
Definition: fsrtlfuncs.h:738
smooth NULL
Definition: ftsmooth.c:416
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG FilterMatch
Definition: fsrtlfuncs.h:738
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2239

◆ FsRtlNotifySetCancelRoutine()

BOOLEAN FsRtlNotifySetCancelRoutine ( IN PIRP  Irp,
IN PNOTIFY_CHANGE NotifyChange  OPTIONAL 
)

Definition at line 424 of file notify.c.

426 {
428 
429  /* Acquire cancel lock */
430  IoAcquireCancelSpinLock(&Irp->CancelIrql);
431 
432  /* If NotifyChange was given */
433  if (NotifyChange)
434  {
435  /* First get cancel routine */
437  Irp->IoStatus.Information = 0;
438  /* Release cancel lock */
439  IoReleaseCancelSpinLock(Irp->CancelIrql);
440  /* If there was a cancel routine */
441  if (CancelRoutine)
442  {
443  /* Decrease reference count */
444  InterlockedDecrement((PLONG)&NotifyChange->ReferenceCount);
445  /* Notify that we removed cancel routine */
446  return TRUE;
447  }
448  }
449  else
450  {
451  /* If IRP is cancel, call FsRtl cancel routine */
452  if (Irp->Cancel)
453  {
455  }
456  else
457  {
458  /* Otherwise, define FsRtl cancel routine as IRP cancel routine */
460  /* Release lock */
461  IoReleaseCancelSpinLock(Irp->CancelIrql);
462  }
463  }
464 
465  /* Return that we didn't removed cancel routine */
466  return FALSE;
467 }
DRIVER_CANCEL * PDRIVER_CANCEL
Definition: iotypes.h:2405
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
IoSetCancelRoutine(Irp, CancelRoutine)
_In_opt_ PDRIVER_CANCEL CancelRoutine
Definition: iofuncs.h:2696
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI FsRtlCancelNotify(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: notify.c:79
#define InterlockedDecrement
Definition: armddk.h:52
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
signed int * PLONG
Definition: retypes.h:5

Referenced by FsRtlNotifyCompleteIrp(), and FsRtlNotifyFilterChangeDirectory().

◆ FsRtlNotifyUninitializeSync()

VOID NTAPI FsRtlNotifyUninitializeSync ( IN PNOTIFY_SYNC NotifySync)

Definition at line 1639 of file notify.c.

1640 {
1641  if (*NotifySync)
1642  {
1643  ExFreePoolWithTag(*NotifySync, 'SNSF');
1644  *NotifySync = NULL;
1645  }
1646 }
smooth NULL
Definition: ftsmooth.c:416
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099

Referenced by CdDeleteVcb(), CdInitializeVcb(), Ext2DestroyVcb(), Ext2InitializeVcb(), FatDeleteVcb(), FFSFreeVcb(), FFSInitializeVcb(), RfsdFreeVcb(), RfsdInitializeVcb(), UDFReleaseVCB(), and VfatCheckForDismount().

◆ FsRtlNotifyUpdateBuffer()

BOOLEAN FsRtlNotifyUpdateBuffer ( OUT PFILE_NOTIFY_INFORMATION  OutputBuffer,
IN ULONG  Action,
IN PSTRING  ParentName,
IN PSTRING  TargetName,
IN PSTRING  StreamName,
IN BOOLEAN  IsUnicode,
IN ULONG  DataLength 
)

Definition at line 473 of file notify.c.

480 {
481  /* Unless there's an issue with buffers, there's no reason to fail */
482  BOOLEAN Succeed = TRUE;
483  ULONG AlreadyWritten = 0, ResultSize;
484 
485  PAGED_CODE();
486 
487  /* Update user buffer with the change that occured
488  * First copy parent name if any
489  * Then copy target name, there's always one
490  * And finally, copy stream name if any
491  * If these names aren't unicode, then convert first
492  */
493  _SEH2_TRY
494  {
495  OutputBuffer->NextEntryOffset = 0;
496  OutputBuffer->Action = Action;
498  if (IsUnicode)
499  {
500  if (ParentName->Length)
501  {
502  RtlCopyMemory(OutputBuffer->FileName, ParentName->Buffer, ParentName->Length);
503  OutputBuffer->FileName[ParentName->Length / sizeof(WCHAR)] = L'\\';
504  AlreadyWritten = ParentName->Length + sizeof(WCHAR);
505  }
506  RtlCopyMemory((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten),
507  TargetName->Buffer, TargetName->Length);
508  if (StreamName)
509  {
510  AlreadyWritten += TargetName->Length;
511  OutputBuffer->FileName[AlreadyWritten / sizeof(WCHAR)] = L':';
512  RtlCopyMemory((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten + sizeof(WCHAR)),
513  StreamName->Buffer, StreamName->Length);
514  }
515  }
516  else
517  {
518  if (!ParentName->Length)
519  {
521  RtlCopyMemory(OutputBuffer->FileName, StreamName->Buffer, StreamName->Length);
522  }
523  else
524  {
525  RtlOemToUnicodeN(OutputBuffer->FileName, OutputBuffer->FileNameLength,
526  &ResultSize, ParentName->Buffer,
527  ParentName->Length);
528  OutputBuffer->FileName[ResultSize / sizeof(WCHAR)] = L'\\';
529  AlreadyWritten = ResultSize + sizeof(WCHAR);
530 
531  RtlOemToUnicodeN((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten),
532  OutputBuffer->FileNameLength, &ResultSize,
533  TargetName->Buffer, TargetName->Length);
534 
535  if (StreamName)
536  {
537  AlreadyWritten += ResultSize;
538  OutputBuffer->FileName[AlreadyWritten / sizeof(WCHAR)] = L':';
539  RtlOemToUnicodeN((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten + sizeof(WCHAR)),
540  OutputBuffer->FileNameLength, &ResultSize,
541  StreamName->Buffer, StreamName->Length);
542  }
543  }
544  }
545  }
547  {
548  Succeed = FALSE;
549  }
550  _SEH2_END;
551 
552  return Succeed;
553 }
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING StreamName
Definition: fsrtlfuncs.h:738
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG Action
Definition: fsrtlfuncs.h:738
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
WCHAR TargetName[256]
Definition: arping.c:27
_SEH2_END
Definition: create.c:4424
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333

Referenced by FsRtlNotifyFilterReportChange().