ReactOS  0.4.15-dev-3719-g41b8715
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;
86  PNOTIFY_CHANGE NotifyChange;
87  PREAL_NOTIFY_SYNC RealNotifySync;
88  BOOLEAN PoolQuotaCharged;
90 
91  /* Get the NOTIFY_CHANGE struct and reset it */
92  NotifyChange = (PNOTIFY_CHANGE)Irp->IoStatus.Information;
93  Irp->IoStatus.Information = 0;
94  /* Reset the cancel routine */
96  /* And release lock */
97  IoReleaseCancelSpinLock(Irp->CancelIrql);
98  /* Get REAL_NOTIFY_SYNC struct */
99  RealNotifySync = NotifyChange->NotifySync;
100 
101  FsRtlNotifyAcquireFastMutex(RealNotifySync);
102 
103  _SEH2_TRY
104  {
105  /* Remove the IRP from the notifications list and mark it pending */
106  RemoveEntryList(&(Irp->Tail.Overlay.ListEntry));
108 
109  /* Now, the tricky part - let's find a buffer big enough to hold the return data */
110  if (NotifyChange->Buffer && NotifyChange->AllocatedBuffer == NULL &&
111  ((Irp->MdlAddress && MmGetSystemAddressForMdl(Irp->MdlAddress) == NotifyChange->Buffer) ||
112  NotifyChange->Buffer == Irp->AssociatedIrp.SystemBuffer))
113  {
114  /* Assume we didn't find any */
115  Buffer = NULL;
116  BufferLength = 0;
117 
118  /* If we don't have IRPs, check if current buffer is big enough */
119  if (IsListEmpty(&NotifyChange->NotifyIrps))
120  {
121  if (NotifyChange->BufferLength >= NotifyChange->DataLength)
122  {
123  BufferLength = NotifyChange->BufferLength;
124  }
125  }
126  else
127  {
128  /* Otherwise, try to look at next IRP available */
129  NotifyIrp = CONTAINING_RECORD(NotifyChange->NotifyIrps.Flink, IRP, Tail.Overlay.ListEntry);
131 
132  /* If its buffer is big enough, get it */
133  if (Stack->Parameters.NotifyDirectory.Length >= NotifyChange->BufferLength)
134  {
135  /* Is it MDL? */
136  if (NotifyIrp->AssociatedIrp.SystemBuffer == NULL)
137  {
138  if (NotifyIrp->MdlAddress != NULL)
139  {
141  }
142  }
143  else
144  {
145  Buffer = NotifyIrp->AssociatedIrp.MasterIrp;
146  }
147 
148  /* Backup our accepted buffer length */
149  BufferLength = Stack->Parameters.NotifyDirectory.Length;
150  if (BufferLength > NotifyChange->BufferLength)
151  {
152  BufferLength = NotifyChange->BufferLength;
153  }
154  }
155  }
156 
157  /* At that point, we *may* have a buffer */
158 
159  /* If it has null length, then note that we won't use it */
160  if (BufferLength == 0)
161  {
162  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
163  }
164  else
165  {
166  /* If we have a buffer length, but no buffer then allocate one */
167  if (Buffer == NULL)
168  {
169  /* Assume we haven't charged quotas */
170  PoolQuotaCharged = FALSE;
171 
172  _SEH2_TRY
173  {
174  /* Charge quotas */
176  PoolQuotaCharged = TRUE;
177 
178  /* Allocate buffer */
180  NotifyChange->AllocatedBuffer = Buffer;
181 
182  /* Copy data in that buffer */
183  RtlCopyMemory(Buffer, NotifyChange->Buffer, NotifyChange->DataLength);
184  NotifyChange->ThisBufferLength = BufferLength;
185  NotifyChange->Buffer = Buffer;
186  }
188  {
189  /* Something went wrong, have we charged quotas? */
190  if (PoolQuotaCharged)
191  {
192  /* We did, return quotas */
194  }
195 
196  /* And notify immediately */
197  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
198  }
199  _SEH2_END;
200  }
201  }
202 
203  /* If we have to notify immediately, ensure that any buffer is 0-ed out */
204  if (NotifyChange->Flags & NOTIFY_IMMEDIATELY)
205  {
206  NotifyChange->Buffer = 0;
207  NotifyChange->AllocatedBuffer = 0;
208  NotifyChange->LastEntry = 0;
209  NotifyChange->DataLength = 0;
210  NotifyChange->ThisBufferLength = 0;
211  }
212  }
213 
214  /* It's now time to complete - data are ready */
215 
216  /* Set appropriate status and complete */
217  Irp->IoStatus.Status = STATUS_CANCELLED;
219 
220  /* If that notification isn't referenced any longer, drop it */
221  if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
222  {
223  /* If it had an allocated buffer, delete */
224  if (NotifyChange->AllocatedBuffer)
225  {
226  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
228  }
229 
230  /* In case of full name, remember subject context for later deletion */
231  if (NotifyChange->FullDirectoryName)
232  {
233  SubjectContext = NotifyChange->SubjectContext;
234  }
235 
236  /* We mustn't have ANY change left anymore */
237  ASSERT(NotifyChange->NotifyList.Flink == NULL);
238  ExFreePoolWithTag(NotifyChange, 0);
239  }
240  }
242  {
243  FsRtlNotifyReleaseFastMutex(RealNotifySync);
244 
245  /* If the subject security context was captured, release and free it */
246  if (SubjectContext)
247  {
250  }
251  }
252  _SEH2_END;
253 }
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
_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:2238
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 BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
PVOID Buffer
Definition: fsrtl.h:90
ULONG ReferenceCount
Definition: fsrtl.h:95
PVOID AllocatedBuffer
Definition: fsrtl.h:89
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:4226
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
_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:600
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
unsigned char BOOLEAN
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:63
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
PEPROCESS OwningProcess
Definition: fsrtl.h:96
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
ULONG BufferLength
Definition: fsrtl.h:91
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InterlockedDecrement
Definition: armddk.h:52
USHORT Flags
Definition: fsrtl.h:86
VOID NTAPI PsChargePoolQuota(_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
Charges the pool quota of a given process. The kind of pool quota to charge is determined by the Pool...
Definition: quota.c:775
PREAL_NOTIFY_SYNC NotifySync
Definition: fsrtl.h:77
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
#define _SEH2_VOLATILE
Definition: pseh2_64.h:169
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_SEH2_END
Definition: create.c:4400
struct _NOTIFY_CHANGE * PNOTIFY_CHANGE
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: access.c:520
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
unsigned int ULONG
Definition: retypes.h:1
#define MmGetSystemAddressForMdl(Mdl)
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define POOL_RAISE_IF_ALLOCATION_FAILURE
IoMarkIrpPending(Irp)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
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 259 of file notify.c.

261 {
262  PLIST_ENTRY NextEntry;
263  PNOTIFY_CHANGE NotifyChange;
264 
265  if (!IsListEmpty(NotifyList))
266  {
267  /* Browse the notifications list to find the matching entry */
268  for (NextEntry = NotifyList->Flink;
269  NextEntry != NotifyList;
270  NextEntry = NextEntry->Flink)
271  {
272  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
273  /* If the current record matches with the given context, it's the good one */
274  if (NotifyChange->FsContext == FsContext && !IsListEmpty(&(NotifyChange->NotifyIrps)))
275  {
277  }
278  }
279  }
280 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
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:418
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:121
Definition: typedefs.h:119
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238

Referenced by FsRtlNotifyFilterChangeDirectory().

◆ FsRtlIsNotifyOnList()

PNOTIFY_CHANGE FsRtlIsNotifyOnList ( IN PLIST_ENTRY  NotifyList,
IN PVOID  FsContext 
)

Definition at line 286 of file notify.c.

288 {
289  PLIST_ENTRY NextEntry;
290  PNOTIFY_CHANGE NotifyChange;
291 
292  if (!IsListEmpty(NotifyList))
293  {
294  /* Browse the notifications list to find the matching entry */
295  for (NextEntry = NotifyList->Flink;
296  NextEntry != NotifyList;
297  NextEntry = NextEntry->Flink)
298  {
299  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
300  /* If the current record matches with the given context, it's the good one */
301  if (NotifyChange->FsContext == FsContext)
302  {
303  return NotifyChange;
304  }
305  }
306  }
307  return NULL;
308 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
PVOID FsContext
Definition: fsrtl.h:78
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
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:121
Definition: typedefs.h:119
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
#define NULL
Definition: types.h:112

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:65
VOID FASTCALL ExAcquireFastMutexUnsafe(IN OUT PFAST_MUTEX FastMutex)
Definition: fmutex.c:75
#define ULONG_PTR
Definition: config.h:101
#define KeGetCurrentThread
Definition: hal.h:55

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 616 of file notify.c.

623 {
625  NotifyList,
626  FsContext,
628  WatchTree,
629  TRUE,
631  NotifyIrp,
632  NULL,
633  NULL,
634  NULL);
635 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
#define TRUE
Definition: types.h:120
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2238
_In_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_opt_ PIRP NotifyIrp
Definition: fsrtlfuncs.h:722
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
#define NULL
Definition: types.h:112
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2238
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING FullDirectoryName
Definition: fltkernel.h:2238
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:773

◆ FsRtlNotifyCleanup()

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

Definition at line 659 of file notify.c.

662 {
663  PNOTIFY_CHANGE NotifyChange;
664  PREAL_NOTIFY_SYNC RealNotifySync;
666 
667  /* Get real structure hidden behind the opaque pointer */
668  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
669 
670  /* Acquire the fast mutex */
671  FsRtlNotifyAcquireFastMutex(RealNotifySync);
672 
673  _SEH2_TRY
674  {
675  /* Find if there's a matching notification with the FsContext */
676  NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
677  if (NotifyChange)
678  {
679  /* Mark it as to know that cleanup is in process */
680  NotifyChange->Flags |= CLEANUP_IN_PROCESS;
681 
682  /* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP status */
683  if (!IsListEmpty(&NotifyChange->NotifyIrps))
684  {
686  }
687 
688  /* Decrease reference number and if 0 is reached, it's time to do complete cleanup */
689  if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount)))
690  {
691  /* Remove it from the notifications list */
692  RemoveEntryList(&NotifyChange->NotifyList);
693 
694  /* In case there was an allocated buffer, free it */
695  if (NotifyChange->AllocatedBuffer)
696  {
697  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
698  ExFreePool(NotifyChange->AllocatedBuffer);
699  }
700 
701  /* In case there the string was set, get the captured subject security context */
702  if (NotifyChange->FullDirectoryName)
703  {
704  SubjectContext = NotifyChange->SubjectContext;
705  }
706 
707  /* Finally, free the notification, as it's not needed anymore */
708  ExFreePoolWithTag(NotifyChange, 'NrSF');
709  }
710  }
711  }
713  {
714  /* Release fast mutex */
715  FsRtlNotifyReleaseFastMutex(RealNotifySync);
716 
717  /* If the subject security context was captured, release and free it */
718  if (SubjectContext)
719  {
722  }
723  }
724  _SEH2_END;
725 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
_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:2238
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:4226
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:418
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
PNOTIFY_CHANGE FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:286
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
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
#define InterlockedDecrement
Definition: armddk.h:52
USHORT Flags
Definition: fsrtl.h:86
#define _SEH2_VOLATILE
Definition: pseh2_64.h:169
_SEH2_END
Definition: create.c:4400
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: access.c:520
#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(), 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 314 of file notify.c.

319 {
320  PVOID Buffer;
322 
323  PAGED_CODE();
324 
325  /* Check if we need to complete */
326  if (!FsRtlNotifySetCancelRoutine(Irp, NotifyChange) && SkipCompletion)
327  {
328  return;
329  }
330 
331  /* No succes => no data to return just complete */
332  if (Status != STATUS_SUCCESS)
333  {
334  goto Completion;
335  }
336 
337  /* Ensure there's something to return */
339  if (!DataLength || Stack->Parameters.NotifyDirectory.Length < DataLength)
340  {
342  goto Completion;
343  }
344 
345  /* Ensture there's a buffer where to find data */
346  if (!NotifyChange->AllocatedBuffer)
347  {
348  Irp->IoStatus.Information = DataLength;
349  NotifyChange->Buffer = NULL;
350  goto Completion;
351  }
352 
353  /* Now, browse all the way to return data
354  * and find the one that will work. We will
355  * return data whatever happens
356  */
357  if (Irp->AssociatedIrp.SystemBuffer)
358  {
359  Buffer = Irp->AssociatedIrp.SystemBuffer;
360  goto CopyAndComplete;
361  }
362 
363  if (Irp->MdlAddress)
364  {
365  Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
366  goto CopyAndComplete;
367  }
368 
369  if (!(Stack->Control & SL_PENDING_RETURNED))
370  {
371  Buffer = Irp->UserBuffer;
372  goto CopyAndComplete;
373  }
374 
376  Irp->AssociatedIrp.SystemBuffer = NotifyChange->AllocatedBuffer;
377  /* Nothing to copy */
378  goto ReleaseAndComplete;
379 
380 CopyAndComplete:
381  _SEH2_TRY
382  {
383  RtlCopyMemory(Buffer, NotifyChange->AllocatedBuffer, DataLength);
384  }
386  {
387  /* Do nothing */
388  }
389  _SEH2_END;
390 
391 ReleaseAndComplete:
392  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
393 
394  /* Release buffer UNLESS it's used */
395  if (NotifyChange->AllocatedBuffer != Irp->AssociatedIrp.SystemBuffer &&
396  NotifyChange->AllocatedBuffer)
397  {
398  ExFreePoolWithTag(NotifyChange->AllocatedBuffer, 0);
399  }
400 
401  /* Prepare for return */
402  NotifyChange->AllocatedBuffer = 0;
403  NotifyChange->ThisBufferLength = 0;
404  Irp->IoStatus.Information = DataLength;
405  NotifyChange->Buffer = NULL;
406 
407  /* Finally complete */
408 Completion:
410  Irp->IoStatus.Status = Status;
412 }
#define SL_PENDING_RETURNED
Definition: iotypes.h:3325
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
_SEH2_TRY
Definition: create.c:4226
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_In_ PIRP Irp
Definition: csq.h:116
#define IoCompleteRequest
Definition: irp.c:1240
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
Definition: bufpool.h:45
#define STATUS_NOTIFY_ENUM_DIR
Definition: ntstatus.h:91
Status
Definition: gdiplustypes.h:24
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_SEH2_END
Definition: create.c:4400
#define IRP_BUFFERED_IO
#define NULL
Definition: types.h:112
BOOLEAN FsRtlNotifySetCancelRoutine(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
Definition: notify.c:448
#define IRP_DEALLOCATE_BUFFER
#define MmGetSystemAddressForMdl(Mdl)
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
IoMarkIrpPending(Irp)
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define IRP_SYNCHRONOUS_PAGING_IO
#define PAGED_CODE()

Referenced by FsRtlNotifyCompleteIrpList(), and FsRtlNotifyFilterChangeDirectory().

◆ FsRtlNotifyCompleteIrpList()

VOID FsRtlNotifyCompleteIrpList ( IN PNOTIFY_CHANGE  NotifyChange,
IN NTSTATUS  Status 
)

Definition at line 418 of file notify.c.

420 {
421  PIRP Irp;
423  PLIST_ENTRY NextEntry;
424 
425  DataLength = NotifyChange->DataLength;
426 
427  NotifyChange->Flags &= (NOTIFY_IMMEDIATELY | WATCH_TREE);
428  NotifyChange->DataLength = 0;
429  NotifyChange->LastEntry = 0;
430 
431  while (!IsListEmpty(&(NotifyChange->NotifyIrps)))
432  {
433  /* We take the first entry */
434  NextEntry = RemoveHeadList(&(NotifyChange->NotifyIrps));
435  Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
436  /* We complete it */
437  FsRtlNotifyCompleteIrp(Irp, NotifyChange, DataLength, Status, TRUE);
438  /* If we're notifying success, just notify first one */
439  if (Status == STATUS_SUCCESS)
440  break;
441  }
442 }
#define TRUE
Definition: types.h:120
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
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
Status
Definition: gdiplustypes.h:24
#define WATCH_TREE
Definition: fsrtl.h:55
Definition: typedefs.h:119
VOID FsRtlNotifyCompleteIrp(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange, IN ULONG DataLength, IN NTSTATUS Status, IN BOOLEAN SkipCompletion)
Definition: notify.c:314
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
unsigned int ULONG
Definition: retypes.h:1
#define STATUS_SUCCESS
Definition: shellext.h:65

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 773 of file notify.c.

784 {
785  ULONG SavedLength;
787  PNOTIFY_CHANGE NotifyChange = NULL;
788  PREAL_NOTIFY_SYNC RealNotifySync;
789 
790  PAGED_CODE();
791 
792  DPRINT("FsRtlNotifyFilterChangeDirectory(): %p, %p, %p, %wZ, %u, %u, %u, %p, %p, %p, %p\n",
795 
796  /* Get real structure hidden behind the opaque pointer */
797  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
798 
799  /* Acquire the fast mutex */
800  FsRtlNotifyAcquireFastMutex(RealNotifySync);
801 
802  _SEH2_TRY
803  {
804  /* If we have no IRP, FSD is performing a cleanup */
805  if (!NotifyIrp)
806  {
807  /* So, we delete */
809  _SEH2_LEAVE;
810  }
811 
812  NotifyIrp->IoStatus.Status = STATUS_SUCCESS;
813  NotifyIrp->IoStatus.Information = (ULONG_PTR)NULL;
814 
816  /* If FileObject's been cleaned up, just return */
817  if (Stack->FileObject->Flags & FO_CLEANUP_COMPLETE)
818  {
820  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
822  _SEH2_LEAVE;
823  }
824 
825  /* Try to find a matching notification has been already registered */
826  NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext);
827  if (NotifyChange)
828  {
829  /* If it's been found, and is cleaned up, immediatly complete */
830  if (NotifyChange->Flags & CLEANUP_IN_PROCESS)
831  {
833  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_CLEANUP;
835  }
836  /* Or if it's about to be deleted, complete */
837  else if (NotifyChange->Flags & DELETE_IN_PROCESS)
838  {
840  NotifyIrp->IoStatus.Status = STATUS_DELETE_PENDING;
842  }
843  /* Complete now if asked to (and not asked to notify later on) */
844  if ((NotifyChange->Flags & NOTIFY_IMMEDIATELY) && !(NotifyChange->Flags & NOTIFY_LATER))
845  {
846  NotifyChange->Flags &= ~NOTIFY_IMMEDIATELY;
848  NotifyIrp->IoStatus.Status = STATUS_NOTIFY_ENUM_DIR;
850  }
851  /* If no data yet, or asked to notify later on, handle */
852  else if (NotifyChange->DataLength == 0 || (NotifyChange->Flags & NOTIFY_LATER))
853  {
854  goto HandleIRP;
855  }
856  /* Else, just complete with we have */
857  else
858  {
859  SavedLength = NotifyChange->DataLength;
860  NotifyChange->DataLength = 0;
861  FsRtlNotifyCompleteIrp(NotifyIrp, NotifyChange, SavedLength, STATUS_SUCCESS, FALSE);
862  }
863 
864  _SEH2_LEAVE;
865  }
866 
867  /* Allocate new notification */
869  sizeof(NOTIFY_CHANGE), 'NrSF');
870  RtlZeroMemory(NotifyChange, sizeof(NOTIFY_CHANGE));
871 
872  /* Set basic information */
873  NotifyChange->NotifySync = NotifySync;
874  NotifyChange->FsContext = FsContext;
875  NotifyChange->StreamID = Stack->FileObject->FsContext;
876  NotifyChange->TraverseCallback = TraverseCallback;
877  NotifyChange->SubjectContext = SubjectContext;
878  NotifyChange->FullDirectoryName = FullDirectoryName;
879  NotifyChange->FilterCallback = FilterCallback;
880  InitializeListHead(&(NotifyChange->NotifyIrps));
881 
882  /* Keep trace of WatchTree */
883  if (WatchTree)
884  {
885  NotifyChange->Flags |= WATCH_TREE;
886  }
887 
888  /* If string is empty, faulty to ANSI */
889  if (FullDirectoryName->Length == 0)
890  {
891  NotifyChange->CharacterSize = sizeof(CHAR);
892  }
893  else
894  {
895  /* If it can't contain WCHAR, it's ANSI */
896  if (FullDirectoryName->Length < sizeof(WCHAR) || ((CHAR*)FullDirectoryName->Buffer)[1] != 0)
897  {
898  NotifyChange->CharacterSize = sizeof(CHAR);
899  }
900  else
901  {
902  NotifyChange->CharacterSize = sizeof(WCHAR);
903  }
904 
905  /* Now, check is user is willing to watch root */
906  if (FullDirectoryName->Length == NotifyChange->CharacterSize)
907  {
908  NotifyChange->Flags |= WATCH_ROOT;
909  }
910  }
911 
912  NotifyChange->CompletionFilter = CompletionFilter;
913 
914  /* In case we have not to ignore buffer , keep its length */
915  if (!IgnoreBuffer)
916  {
917  NotifyChange->BufferLength = Stack->Parameters.NotifyDirectory.Length;
918  }
919 
920  NotifyChange->OwningProcess = NotifyIrp->Tail.Overlay.Thread->ThreadsProcess;
921 
922  /* Insert the notification into the notification list */
923  InsertTailList(NotifyList, &(NotifyChange->NotifyList));
924 
925  NotifyChange->ReferenceCount = 1;
926 
927 HandleIRP:
928  /* Associate the notification to the IRP */
929  NotifyIrp->IoStatus.Information = (ULONG_PTR)NotifyChange;
930  /* The IRP is pending */
932  /* Insert the IRP in the IRP list */
933  InsertTailList(&(NotifyChange->NotifyIrps), &(NotifyIrp->Tail.Overlay.ListEntry));
934  /* Increment reference count */
935  InterlockedIncrement((PLONG)&(NotifyChange->ReferenceCount));
936  /* Set cancel routine to FsRtl one */
938  }
940  {
941  /* Release fast mutex */
942  FsRtlNotifyReleaseFastMutex(RealNotifySync);
943 
944  /* If the subject security context was captured and there's no notify */
945  if (SubjectContext && (!NotifyChange || NotifyChange->FullDirectoryName))
946  {
949  }
950  }
951  _SEH2_END;
952 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
_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:2238
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:2238
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:2238
ULONG DataLength
Definition: fsrtl.h:93
_SEH2_TRY
Definition: create.c:4226
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
_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:600
#define FALSE
Definition: types.h:117
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN IgnoreBuffer
Definition: fltkernel.h:2238
PNOTIFY_CHANGE FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:286
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
#define IoCompleteRequest
Definition: irp.c:1240
#define CLEANUP_IN_PROCESS
Definition: fsrtl.h:57
#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:259
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:314
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_SEH2_END
Definition: create.c:4400
LIST_ENTRY NotifyList
Definition: fsrtl.h:83
#define InterlockedIncrement
Definition: armddk.h:53
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
_SEH2_FINALLY
Definition: create.c:4371
#define NULL
Definition: types.h:112
BOOLEAN FsRtlNotifySetCancelRoutine(IN PIRP Irp, IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
Definition: notify.c:448
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2238
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: access.c:520
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:2238
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_LEAVE
Definition: filesup.c:20
#define DPRINT
Definition: sndvol32.h:71
ULONG CompletionFilter
Definition: fsrtl.h:88
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:2238
#define PAGED_CODE()

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 997 of file notify.c.

1007 {
1008  PIRP Irp;
1010  USHORT FullPosition;
1011  PLIST_ENTRY NextEntry;
1013  PNOTIFY_CHANGE NotifyChange;
1014  PREAL_NOTIFY_SYNC RealNotifySync;
1015  PFILE_NOTIFY_INFORMATION FileNotifyInfo;
1016  BOOLEAN IsStream, IsParent, PoolQuotaCharged;
1017  STRING TargetDirectory, TargetName, ParentName, IntNormalizedParentName;
1018  ULONG NumberOfBytes, TargetNumberOfParts, FullNumberOfParts, LastPartOffset, ParentNameOffset, ParentNameLength;
1019  ULONG DataLength, AlignedDataLength;
1020 
1021  TargetDirectory.Length = 0;
1022  TargetDirectory.MaximumLength = 0;
1023  TargetDirectory.Buffer = NULL;
1024  TargetName.Length = 0;
1025  TargetName.MaximumLength = 0;
1026  TargetName.Buffer = NULL;
1027  ParentName.Length = 0;
1028  ParentName.MaximumLength = 0;
1029  ParentName.Buffer = NULL;
1030  IsStream = FALSE;
1031 
1032  PAGED_CODE();
1033 
1034  DPRINT("FsRtlNotifyFilterReportChange(%p, %p, %p, %u, %p, %p, %p, %x, %x, %p, %p)\n",
1037 
1038  /* We need offset in name */
1040  {
1041  return;
1042  }
1043 
1044  /* Get real structure hidden behind the opaque pointer */
1045  RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync;
1046  /* Acquire lock - will be released in finally block */
1047  FsRtlNotifyAcquireFastMutex(RealNotifySync);
1048  _SEH2_TRY
1049  {
1050  /* Browse all the registered notifications we have */
1051  for (NextEntry = NotifyList->Flink; NextEntry != NotifyList;
1052  NextEntry = NextEntry->Flink)
1053  {
1054  /* Try to find an entry matching our change */
1055  NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
1056  if (FullTargetName != NULL)
1057  {
1058  ASSERT(NotifyChange->FullDirectoryName != NULL);
1059  if (!NotifyChange->FullDirectoryName->Length)
1060  {
1061  continue;
1062  }
1063 
1064  if (!(FilterMatch & NotifyChange->CompletionFilter))
1065  {
1066  continue;
1067  }
1068 
1069  /* If no normalized name provided, construct it from full target name */
1070  if (NormalizedParentName == NULL)
1071  {
1072  IntNormalizedParentName.Buffer = FullTargetName->Buffer;
1073  if (TargetNameOffset != NotifyChange->CharacterSize)
1074  {
1075  IntNormalizedParentName.MaximumLength =
1076  IntNormalizedParentName.Length = TargetNameOffset - NotifyChange->CharacterSize;
1077  }
1078  else
1079  {
1080  IntNormalizedParentName.MaximumLength =
1081  IntNormalizedParentName.Length = TargetNameOffset;
1082  }
1083  NormalizedParentName = &IntNormalizedParentName;
1084  }
1085 
1086  /* heh? Watched directory bigger than changed file? */
1087  if (NormalizedParentName->Length < NotifyChange->FullDirectoryName->Length)
1088  {
1089  continue;
1090  }
1091 
1092  /* Same len => parent */
1093  if (NormalizedParentName->Length == NotifyChange->FullDirectoryName->Length)
1094  {
1095  IsParent = TRUE;
1096  }
1097  /* If not, then, we have to be watching the tree, otherwise we don't have to report such changes */
1098  else if (!(NotifyChange->Flags & WATCH_TREE))
1099  {
1100  continue;
1101  }
1102  /* And finally, we've to check we're properly \-terminated */
1103  else
1104  {
1105  if (!(NotifyChange->Flags & WATCH_ROOT))
1106  {
1107  if (NotifyChange->CharacterSize == sizeof(CHAR))
1108  {
1109  if (((PSTR)NormalizedParentName->Buffer)[NotifyChange->FullDirectoryName->Length] != '\\')
1110  {
1111  continue;
1112  }
1113  }
1114  else
1115  {
1116  if (((PWSTR)NormalizedParentName->Buffer)[NotifyChange->FullDirectoryName->Length / sizeof (WCHAR)] != L'\\')
1117  {
1118  continue;
1119  }
1120  }
1121  }
1122 
1123  IsParent = FALSE;
1124  }
1125 
1126  /* If len matches, then check that both name are equal */
1127  if (!RtlEqualMemory(NormalizedParentName->Buffer, NotifyChange->FullDirectoryName->Buffer,
1128  NotifyChange->FullDirectoryName->Length))
1129  {
1130  continue;
1131  }
1132 
1133  /* Call traverse callback (only if we have to traverse ;-)) */
1134  if (!IsParent
1135  && NotifyChange->TraverseCallback != NULL
1136  && !NotifyChange->TraverseCallback(NotifyChange->FsContext,
1137  TargetContext,
1138  NotifyChange->SubjectContext))
1139  {
1140  continue;
1141  }
1142 
1143  /* And then, filter callback if provided */
1144  if (NotifyChange->FilterCallback != NULL
1145  && FilterContext != NULL
1146  && !NotifyChange->FilterCallback(NotifyChange->FsContext, FilterContext))
1147  {
1148  continue;
1149  }
1150  }
1151  /* We have a stream! */
1152  else
1153  {
1154  ASSERT(NotifyChange->FullDirectoryName == NULL);
1155  if (TargetContext != NotifyChange->SubjectContext)
1156  {
1157  continue;
1158  }
1159 
1160  ParentName.Buffer = NULL;
1161  ParentName.Length = 0;
1162  IsStream = TRUE;
1163  IsParent = FALSE;
1164  }
1165 
1166  /* If we don't have to notify immediately, prepare for output */
1167  if (!(NotifyChange->Flags & NOTIFY_IMMEDIATELY))
1168  {
1169  /* If we have something to output... */
1170  if (NotifyChange->BufferLength)
1171  {
1172  /* Get size of the output */
1173  NumberOfBytes = 0;
1174  Irp = NULL;
1175  if (!NotifyChange->ThisBufferLength)
1176  {
1177  if (IsListEmpty(&NotifyChange->NotifyIrps))
1178  {
1179  NumberOfBytes = NotifyChange->BufferLength;
1180  }
1181  else
1182  {
1183  Irp = CONTAINING_RECORD(NotifyChange->NotifyIrps.Flink, IRP, Tail.Overlay.ListEntry);
1185  NumberOfBytes = Stack->Parameters.NotifyDirectory.Length;
1186  }
1187  }
1188  else
1189  {
1190  NumberOfBytes = NotifyChange->ThisBufferLength;
1191  }
1192 
1193  /* If we're matching parent, we don't care about parent (redundant) */
1194  if (IsParent)
1195  {
1196  ParentName.Length = 0;
1197  }
1198  else
1199  {
1200  /* If we don't deal with streams, some more work is required */
1201  if (!IsStream)
1202  {
1203  if (NotifyChange->Flags & WATCH_ROOT ||
1204  (NormalizedParentName->Buffer != FullTargetName->Buffer))
1205  {
1206  /* Construct TargetDirectory if we don't have it yet */
1207  if (TargetDirectory.Buffer == NULL)
1208  {
1209  TargetDirectory.Buffer = FullTargetName->Buffer;
1210  TargetDirectory.Length = TargetNameOffset;
1211  if (TargetNameOffset != NotifyChange->CharacterSize)
1212  {
1213  TargetDirectory.Length = TargetNameOffset - NotifyChange->CharacterSize;
1214  }
1215  TargetDirectory.MaximumLength = TargetDirectory.Length;
1216  }
1217  /* Now, we start looking for matching parts (unless we watch root) */
1218  TargetNumberOfParts = 0;
1219  if (!(NotifyChange->Flags & WATCH_ROOT))
1220  {
1221  FullNumberOfParts = 1;
1222  if (NotifyChange->CharacterSize == sizeof(CHAR))
1223  {
1225  TargetDirectory.Length, PSTR, '\\');
1226  }
1227  else
1228  {
1230  TargetDirectory.Length / sizeof(WCHAR), PWSTR, L'\\');
1231  LastPartOffset *= NotifyChange->CharacterSize;
1232  }
1233  }
1234 
1235  /* Then, we can construct proper parent name */
1236  ParentNameOffset = NotifyChange->CharacterSize + LastPartOffset;
1237  ParentName.Buffer = &TargetDirectory.Buffer[ParentNameOffset];
1238  ParentNameLength = TargetDirectory.Length;
1239  }
1240  else
1241  {
1242  /* Construct parent name even for streams */
1243  ParentName.Buffer = &NormalizedParentName->Buffer[NotifyChange->FullDirectoryName->Length] + NotifyChange->CharacterSize;
1244  ParentNameLength = NormalizedParentName->Length - NotifyChange->FullDirectoryName->Length;
1245  ParentNameOffset = NotifyChange->CharacterSize;
1246  }
1247  ParentNameLength -= ParentNameOffset;
1248  ParentName.Length = ParentNameLength;
1249  ParentName.MaximumLength = ParentNameLength;
1250  }
1251  }
1252 
1253  /* Start to count amount of data to write, we've first the structure itself */
1255 
1256  /* If stream, we'll just append stream name */
1257  if (IsStream)
1258  {
1259  ASSERT(StreamName != NULL);
1260  DataLength += StreamName->Length;
1261  }
1262  else
1263  {
1264  /* If not parent, we've to append parent name */
1265  if (!IsParent)
1266  {
1267  if (NotifyChange->CharacterSize == sizeof(CHAR))
1268  {
1270  }
1271  else
1272  {
1273  DataLength += ParentName.Length;
1274  }
1275  DataLength += sizeof(WCHAR);
1276  }
1277 
1278  /* Look for target name & construct it, if required */
1279  if (TargetName.Buffer == NULL)
1280  {
1281  TargetName.Buffer = &FullTargetName->Buffer[TargetNameOffset];
1282  TargetName.Length =
1283  TargetName.MaximumLength = FullTargetName->Length - TargetNameOffset;
1284  }
1285 
1286  /* Then, we will append it as well */
1287  if (NotifyChange->CharacterSize == sizeof(CHAR))
1288  {
1290  }
1291  else
1292  {
1293  DataLength += TargetName.Length;
1294  }
1295 
1296  /* If we also had a stream name, then we can append it as well */
1297  if (StreamName != NULL)
1298  {
1299  if (NotifyChange->CharacterSize == sizeof(WCHAR))
1300  {
1301  DataLength += StreamName->Length + sizeof(WCHAR);
1302  }
1303  else
1304  {
1306  }
1307  }
1308  }
1309 
1310  /* Get the position where we can put our data (aligned!) */
1311  AlignedDataLength = ROUND_UP(NotifyChange->DataLength, sizeof(ULONG));
1312  /* If it's higher than buffer length, then, bail out without outputing */
1313  if (DataLength > NumberOfBytes || AlignedDataLength + DataLength > NumberOfBytes)
1314  {
1315  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1316  }
1317  else
1318  {
1319  OutputBuffer = NULL;
1320  FileNotifyInfo = NULL;
1321  /* If we already had a buffer, update last entry position */
1322  if (NotifyChange->Buffer != NULL)
1323  {
1324  FileNotifyInfo = (PVOID)((ULONG_PTR)NotifyChange->Buffer + NotifyChange->LastEntry);
1325  FileNotifyInfo->NextEntryOffset = AlignedDataLength - NotifyChange->LastEntry;
1326  NotifyChange->LastEntry = AlignedDataLength;
1327  /* And get our output buffer */
1328  OutputBuffer = (PVOID)((ULONG_PTR)NotifyChange->Buffer + AlignedDataLength);
1329  }
1330  /* If we hadn't buffer, try to find one */
1331  else if (Irp != NULL)
1332  {
1333  if (Irp->AssociatedIrp.SystemBuffer != NULL)
1334  {
1335  OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
1336  }
1337  else if (Irp->MdlAddress != NULL)
1338  {
1339  OutputBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1340  }
1341 
1342  NotifyChange->Buffer = OutputBuffer;
1343  NotifyChange->ThisBufferLength = NumberOfBytes;
1344  }
1345 
1346  /* If we couldn't find one, then allocate one */
1347  if (NotifyChange->Buffer == NULL)
1348  {
1349  /* Assign the length buffer */
1350  NotifyChange->ThisBufferLength = NumberOfBytes;
1351 
1352  /* Assume we have not charged quotas */
1353  PoolQuotaCharged = FALSE;
1354  _SEH2_TRY
1355  {
1356  /* And charge quotas */
1357  PsChargePoolQuota(NotifyChange->OwningProcess, PagedPool, NotifyChange->ThisBufferLength);
1358  PoolQuotaCharged = TRUE;
1361  NotifyChange->Buffer = OutputBuffer;
1362  NotifyChange->AllocatedBuffer = OutputBuffer;
1363  }
1364  /* If something went wrong during allocation, notify immediately instead of outputing */
1366  {
1367  if (PoolQuotaCharged)
1368  {
1369  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
1370  }
1371  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1372  }
1373  _SEH2_END;
1374  }
1375 
1376  /* Finally, if we have a buffer, fill it in! */
1377  if (OutputBuffer != NULL)
1378  {
1380  Action, &ParentName, &TargetName,
1381  StreamName, NotifyChange->CharacterSize == sizeof(WCHAR),
1382  DataLength))
1383  {
1384  NotifyChange->DataLength = DataLength + AlignedDataLength;
1385  }
1386  /* If it failed, notify immediately */
1387  else
1388  {
1389  NotifyChange->Flags |= NOTIFY_IMMEDIATELY;
1390  }
1391  }
1392  }
1393 
1394  /* If we have to notify right now (something went wrong?) */
1395  if (NotifyChange->Flags & NOTIFY_IMMEDIATELY)
1396  {
1397  /* Ensure that all our buffers are NULL */
1398  if (NotifyChange->Buffer != NULL)
1399  {
1400  if (NotifyChange->AllocatedBuffer != NULL)
1401  {
1402  PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
1404  }
1405 
1406  NotifyChange->Buffer = NULL;
1407  NotifyChange->AllocatedBuffer = NULL;
1408  NotifyChange->LastEntry = 0;
1409  NotifyChange->DataLength = 0;
1410  NotifyChange->ThisBufferLength = 0;
1411  }
1412  }
1413  }
1414  }
1415 
1416  /* If asking for old name in case of a rename, notify later on,
1417  * so that we can wait for new name.
1418  * http://msdn.microsoft.com/en-us/library/dn392331.aspx
1419  */
1421  {
1422  NotifyChange->Flags |= NOTIFY_LATER;
1423  }
1424  else
1425  {
1426  NotifyChange->Flags &= ~NOTIFY_LATER;
1427  if (!IsListEmpty(&NotifyChange->NotifyIrps))
1428  {
1430  }
1431  }
1432  }
1433  }
1435  {
1436  FsRtlNotifyReleaseFastMutex(RealNotifySync);
1437  }
1438  _SEH2_END;
1439 }
PVOID FsContext
Definition: fsrtl.h:78
#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
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
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
_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:497
ULONG DataLength
Definition: fsrtl.h:93
_SEH2_TRY
Definition: create.c:4226
_In_ PLIST_ENTRY _In_ PSTRING FullTargetName
Definition: fsrtlfuncs.h:738
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
struct _REAL_NOTIFY_SYNC * PREAL_NOTIFY_SYNC
void * Buffer
Definition: sprintf.c:453
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
VOID FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange, IN NTSTATUS Status)
Definition: notify.c:418
PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fsrtl.h:81
unsigned char BOOLEAN
LIST_ENTRY NotifyIrps
Definition: fsrtl.h:84
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
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
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:859
#define TAG_FS_NOTIFICATIONS
Definition: tag.h:63
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING StreamName
Definition: fsrtlfuncs.h:738
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define WATCH_TREE
Definition: fsrtl.h:55
#define ASSERT(a)
Definition: mode.c:44
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 EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define NOTIFY_LATER
Definition: fsrtl.h:58
PEPROCESS OwningProcess
Definition: fsrtl.h:96
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
ULONG BufferLength
Definition: fsrtl.h:91
std::wstring STRING
Definition: fontsub.cpp:33
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT Flags
Definition: fsrtl.h:86
VOID NTAPI PsChargePoolQuota(_In_ PEPROCESS Process, _In_ POOL_TYPE PoolType, _In_ SIZE_T Amount)
Charges the pool quota of a given process. The kind of pool quota to charge is determined by the Pool...
Definition: quota.c:775
WCHAR TargetName[256]
Definition: arping.c:27
Definition: typedefs.h:119
#define FsRtlNotifyGetLastPartOffset(FullLen, TargLen, Type, Chr)
Definition: notify.c:52
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
_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:4400
unsigned short USHORT
Definition: pedump.c:61
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT TargetNameOffset
Definition: fsrtlfuncs.h:738
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
signed char * PSTR
Definition: retypes.h:7
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
_SEH2_FINALLY
Definition: create.c:4371
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1035
#define NULL
Definition: types.h:112
UCHAR CharacterSize
Definition: fsrtl.h:87
#define NOTIFY_IMMEDIATELY
Definition: fsrtl.h:56
unsigned int ULONG
Definition: retypes.h:1
#define MmGetSystemAddressForMdl(Mdl)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
ULONG CompletionFilter
Definition: fsrtl.h:88
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define CHAR(Char)
#define RtlOemStringToCountedUnicodeSize(STRING)
#define PAGED_CODE()
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 1487 of file notify.c.

1497 {
1499  NotifyList,
1500  FsContext,
1502  WatchTree,
1503  IgnoreBuffer,
1505  NotifyIrp,
1508  NULL);
1509 }
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2238
_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:2238
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2238
_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:2238
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
#define NULL
Definition: types.h:112
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2238
_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:2238
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING FullDirectoryName
Definition: fltkernel.h:2238
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:773

Referenced by _Requires_lock_held_(), Ext2Cleanup(), Ext2IsFileRemovable(), Ext2NotifyChangeDirectory(), 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 1552 of file notify.c.

1561 {
1562  FsRtlNotifyFilterReportChange(NotifySync,
1563  NotifyList,
1566  StreamName,
1568  FilterMatch,
1569  Action,
1570  TargetContext,
1571  NULL);
1572 }
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:997
_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
_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 _In_opt_ PVOID TargetContext
Definition: fsrtlfuncs.h:738
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT TargetNameOffset
Definition: fsrtlfuncs.h:738
_Inout_ PLIST_ENTRY NotifyList
Definition: fltkernel.h:2238
#define NULL
Definition: types.h:112

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

◆ FsRtlNotifyInitializeSync()

VOID NTAPI FsRtlNotifyInitializeSync ( IN PNOTIFY_SYNC NotifySync)

Definition at line 1590 of file notify.c.

1591 {
1592  PREAL_NOTIFY_SYNC RealNotifySync;
1593 
1594  *NotifySync = NULL;
1595 
1597  sizeof(REAL_NOTIFY_SYNC), 'SNSF');
1598  ExInitializeFastMutex(&(RealNotifySync->FastMutex));
1599  RealNotifySync->OwningThread = 0;
1600  RealNotifySync->OwnerCount = 0;
1601 
1602  *NotifySync = RealNotifySync;
1603 }
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NULL
Definition: types.h:112
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(), mount_vol(), 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 1633 of file notify.c.

1638 {
1639  FsRtlNotifyFilterReportChange(NotifySync,
1640  NotifyList,
1642  FullTargetName->Length - *FileNamePartLength,
1643  NULL,
1644  NULL,
1645  FilterMatch,
1646  0,
1647  NULL,
1648  NULL);
1649 }
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:997
_In_ PLIST_ENTRY _In_ PSTRING FullTargetName
Definition: fsrtlfuncs.h:738
_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:2238
#define NULL
Definition: types.h:112

◆ FsRtlNotifySetCancelRoutine()

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

Definition at line 448 of file notify.c.

450 {
452 
453  /* Acquire cancel lock */
454  IoAcquireCancelSpinLock(&Irp->CancelIrql);
455 
456  /* If NotifyChange was given */
457  if (NotifyChange)
458  {
459  /* First get cancel routine */
461  Irp->IoStatus.Information = 0;
462  /* Release cancel lock */
463  IoReleaseCancelSpinLock(Irp->CancelIrql);
464  /* If there was a cancel routine */
465  if (CancelRoutine)
466  {
467  /* Decrease reference count */
468  InterlockedDecrement((PLONG)&NotifyChange->ReferenceCount);
469  /* Notify that we removed cancel routine */
470  return TRUE;
471  }
472  }
473  else
474  {
475  /* If IRP is cancel, call FsRtl cancel routine */
476  if (Irp->Cancel)
477  {
479  }
480  else
481  {
482  /* Otherwise, define FsRtl cancel routine as IRP cancel routine */
484  /* Release lock */
485  IoReleaseCancelSpinLock(Irp->CancelIrql);
486  }
487  }
488 
489  /* Return that we didn't removed cancel routine */
490  return FALSE;
491 }
DRIVER_CANCEL * PDRIVER_CANCEL
Definition: iotypes.h:2759
#define TRUE
Definition: types.h:120
VOID NTAPI IoAcquireCancelSpinLock(OUT PKIRQL Irql)
Definition: util.c:56
IoSetCancelRoutine(Irp, CancelRoutine)
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
_In_opt_ PDRIVER_CANCEL CancelRoutine
Definition: iofuncs.h:2744
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
#define NULL
Definition: types.h:112
signed int * PLONG
Definition: retypes.h:5

Referenced by FsRtlNotifyCompleteIrp(), and FsRtlNotifyFilterChangeDirectory().

◆ FsRtlNotifyUninitializeSync()

VOID NTAPI FsRtlNotifyUninitializeSync ( IN PNOTIFY_SYNC NotifySync)

Definition at line 1668 of file notify.c.

1669 {
1670  if (*NotifySync)
1671  {
1672  ExFreePoolWithTag(*NotifySync, 'SNSF');
1673  *NotifySync = NULL;
1674  }
1675 }
#define NULL
Definition: types.h:112
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099

Referenced by CdDeleteVcb(), CdInitializeVcb(), Ext2DestroyVcb(), Ext2InitializeVcb(), FatDeleteVcb(), 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 497 of file notify.c.

504 {
505  /* Unless there's an issue with buffers, there's no reason to fail */
506  BOOLEAN Succeed = TRUE;
507  ULONG AlreadyWritten = 0, ResultSize;
508 
509  PAGED_CODE();
510 
511  /* Update user buffer with the change that occured
512  * First copy parent name if any
513  * Then copy target name, there's always one
514  * And finally, copy stream name if any
515  * If these names aren't unicode, then convert first
516  */
517  _SEH2_TRY
518  {
519  OutputBuffer->NextEntryOffset = 0;
520  OutputBuffer->Action = Action;
522  if (IsUnicode)
523  {
524  if (ParentName->Length)
525  {
526  RtlCopyMemory(OutputBuffer->FileName, ParentName->Buffer, ParentName->Length);
527  OutputBuffer->FileName[ParentName->Length / sizeof(WCHAR)] = L'\\';
528  AlreadyWritten = ParentName->Length + sizeof(WCHAR);
529  }
530  RtlCopyMemory((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten),
531  TargetName->Buffer, TargetName->Length);
532  if (StreamName)
533  {
534  AlreadyWritten += TargetName->Length;
535  OutputBuffer->FileName[AlreadyWritten / sizeof(WCHAR)] = L':';
536  RtlCopyMemory((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten + sizeof(WCHAR)),
537  StreamName->Buffer, StreamName->Length);
538  }
539  }
540  else
541  {
542  if (!ParentName->Length)
543  {
545  RtlCopyMemory(OutputBuffer->FileName, StreamName->Buffer, StreamName->Length);
546  }
547  else
548  {
549  RtlOemToUnicodeN(OutputBuffer->FileName, OutputBuffer->FileNameLength,
550  &ResultSize, ParentName->Buffer,
551  ParentName->Length);
552  OutputBuffer->FileName[ResultSize / sizeof(WCHAR)] = L'\\';
553  AlreadyWritten = ResultSize + sizeof(WCHAR);
554 
555  RtlOemToUnicodeN((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten),
556  OutputBuffer->FileNameLength, &ResultSize,
557  TargetName->Buffer, TargetName->Length);
558 
559  if (StreamName)
560  {
561  AlreadyWritten += ResultSize;
562  OutputBuffer->FileName[AlreadyWritten / sizeof(WCHAR)] = L':';
563  RtlOemToUnicodeN((PVOID)((ULONG_PTR)OutputBuffer->FileName + AlreadyWritten + sizeof(WCHAR)),
564  OutputBuffer->FileNameLength, &ResultSize,
565  StreamName->Buffer, StreamName->Length);
566  }
567  }
568  }
569  }
571  {
572  Succeed = FALSE;
573  }
574  _SEH2_END;
575 
576  return Succeed;
577 }
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define TRUE
Definition: types.h:120
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1437
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:859
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING StreamName
Definition: fsrtlfuncs.h:738
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
WCHAR TargetName[256]
Definition: arping.c:27
_SEH2_END
Definition: create.c:4400
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define PAGED_CODE()

Referenced by FsRtlNotifyFilterReportChange().